Типы транзакций 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 обеспечивает консенсус без центрального сервера.
Ordinals, Inscriptions, BRC-20 и Runes
Taproot открыл Bitcoin для произвольных данных: witness может быть до ~4 МБ, и эта область получает 75% скидку по комиссии. На этом фундаменте в 2023-2024 выросла отдельная экосистема, которая к 2026 насчитывает >90M inscriptions и сотни миллионов долларов вторичных продаж в месяц.
Ordinal Theory (Casey Rodarmor, январь 2023)
Idея: каждой из 2.1 квадриллиона satoshi присваивается уникальный порядковый номер — ordinal. Это не on-chain информация, а off-chain интерпретация последовательности транзакций по правилам:
Правила нумерации:
1. Sat нумеруются в порядке майнинга (первый sat в coinbase каждого блока имеет известный номер)
2. При трате UTXO: sat-ы идут "in order" -- FIFO от inputs к outputs
3. Любой клиент может детерминистически рассчитать, какие sat-ы лежат в каком UTXO
Rarity tiers (произвольная классификация):
- common, uncommon (первый sat блока), rare (первый блока difficulty epoch),
epic (первый блока halving), legendary (первый цикла), mythic (genesis sat)
Сам Bitcoin консенсус ordinals не знает: это чисто индексер на стороне клиента. Это важно: ordinals не требуют softfork, они работают на любом полном узле.
Inscriptions: писать данные в Taproot witness
Taproot script-path тратит даёт лазейку: можно положить произвольный payload в witness через OP_FALSE OP_IF ... OP_ENDIF (это “envelope” — никогда не выполняется). По соглашению Ordinals:
Inscription envelope (упрощённо):
OP_FALSE
OP_IF
OP_PUSH "ord" // protocol marker
OP_PUSH 1 // tag = content-type
OP_PUSH "image/png"
OP_PUSH 0 // tag = body
OP_PUSH <chunk_1>
OP_PUSH <chunk_2> // данные нарезаются по 520 байт
...
OP_ENDIF
<regular taproot script>
Inscription “привязывается” к первому sat первого input reveal-транзакции. Двухэтапный процесс:
- Commit transaction: обычный send на Taproot-адрес, derived от script с inscription envelope.
- Reveal transaction: трата того UTXO с раскрытием script-path — envelope становится частью witness и попадает в blockchain.
BRC-20: токены через JSON-инскрипции
Domo (март 2023) предложил простейший token-стандарт без смарт-контрактов: содержимое inscription — это JSON.
// deploy: создание токена
{ "p": "brc-20", "op": "deploy", "tick": "ordi", "max": "21000000", "lim": "1000" }
// mint: минт N токенов на адрес reveal
{ "p": "brc-20", "op": "mint", "tick": "ordi", "amt": "1000" }
// transfer: двухступенчатый -- inscribe + send sat
{ "p": "brc-20", "op": "transfer", "tick": "ordi", "amt": "100" }
Bitcoin не знает про BRC-20. Балансы вычисляют off-chain индексеры (Unisat, OKX). Это значит: правда хранится в социальном консенсусе и в коде индексеров, а не в L1.
Runes: native UTXO commitments (апрель 2024)
К 2024 BRC-20 создал серьёзный mempool-фоновый шум: каждый transfer = два шага inscriptions, плюс многочисленные “junk UTXO”. Casey предложил Runes — альтернативный фунгибл-стандарт.
Ключевая разница:
BRC-20: данные в taproot witness, balances в индексере
Runes: данные в OP_RETURN (макс 80 байт), balances в самих UTXO
Runestone (упрощённый формат OP_RETURN):
OP_RETURN OP_PUSH("RUNE")
encoded edicts: [(rune_id, amount, output_index), ...]
Каждый UTXO "содержит" определённое количество rune-токенов.
Send = создать output с edict, направляющим amount туда.
Преимущества:
- Native UTXO model: транзакция выглядит как обычный Bitcoin перевод. Не нужно “transfer inscription, потом send sat”.
- Меньше места: OP_RETURN до 80 байт против ~1-2 КБ для BRC-20 transfer-цикла.
- Один индексер per chain: Bitcoin Core видит OP_RETURN — любой узел может построить state.
К Q1 2026 Runes занимают ~35% всех metadata-транзакций Bitcoin и в значительной мере вытеснили BRC-20 для активного трейдинга.
Экономический эффект на mempool и fees
2023 (Ordinals/BRC-20 boom):
Bitcoin mempool часто >300 MB
Median fee: $5-50/tx (vs ~$1 в спокойные периоды)
Halving 2024 + inscriptions => майнерская выручка 40% из fees (рекорд)
2026:
Runes "очистили" mempool -- меньше witness-bloat
Inscriptions сместились в Stamps, Atomicals -- разные технологии
Fee market стал двусторонним: BTC payments vs metadata vs L2 settlements (Lightning, BitVM, rollups)
Для разработчика это означает: fee estimation теперь зависит не только от количества Bitcoin-платежей, но и от inscription-волн. Кошельки с агрессивной CPFP-логикой выигрывают, а статические fee из 2017 ломаются.