Разработка сервиса инскрипций на Bitcoin
Ordinals и инскрипции перевернули представление о том, что можно хранить в Bitcoin. Технически это не смарт-контракты и не токены в EVM-смысле — это данные, встроенные в witness часть SegWit-транзакций и привязанные к конкретным сатоши через протокол нумерации Ordinals. Если вы хотите сервис для минта, трансфера или отображения инскрипций — это отдельная инфраструктурная задача, не решаемая стандартными Bitcoin библиотеками.
Как работают инскрипции на уровне протокола
Инскрипция создаётся через commit-reveal паттерн из двух транзакций:
Commit TX: создаёт P2TR (Pay-to-Taproot, BIP-341) output, скрипт которого содержит данные инскрипции в envelope — специальном формате внутри Tapscript:
OP_FALSE
OP_IF
OP_PUSH "ord" # маркер протокола
OP_PUSH 1 # field: content-type
OP_PUSH "image/png"
OP_PUSH 0 # field: content
OP_PUSH <data_chunk_1>
OP_PUSH <data_chunk_2> # данные чанками по 520 байт
...
OP_ENDIF
<pubkey> OP_CHECKSIG
Данные находятся внутри OP_IF...OP_ENDIF ветки которая никогда не исполняется — это делает их witness data, а не исполняемым кодом. Лимит на witness данные: ~400KB на транзакцию (после Taproot снятие ограничений на witness размер).
Reveal TX: тратит commit output, раскрывая скрипт и встраивая данные инскрипции в blockchain.
Инскрипция привязывается к первому сатоши первого input'а reveal транзакции по правилам Ordinals ordinal theory.
Архитектура сервиса
Компоненты
Bitcoin нода — обязательна, без неё не обойтись. Bitcoind с txindex=1 для поиска транзакций по hash. Для работы с Ordinals нужен также ord индексатор (https://github.com/ordinals/ord) — отдельный процесс, который синхронизирует свою базу SQLite с состоянием ноды. Альтернатива: Hiro Ordinals API или OrdinalsBot API — если не хотите держать собственную инфраструктуру.
Wallet management. Каждый пользователь получает Bitcoin адрес (P2TR — taproot, начинается с bc1p). Библиотеки: bitcoinjs-lib (JavaScript/TypeScript), rust-bitcoin (Rust), python-bitcoinlib. Для HD-кошельков — BIP-32/84/86 деривация.
Fee estimation. Комиссии в Bitcoin волатильны. Сервис должен использовать актуальные fee rates: estimatesmartfee через RPC или внешние API (mempool.space API, Blockstream API). Для инскрипций с большими данными fee — основная статья затрат: при 50 sat/vByte и 200KB инскрипции — ~0.1 BTC.
Flow создания инскрипции
import * as bitcoin from 'bitcoinjs-lib';
import { ECPairFactory } from 'ecpair';
import * as ecc from 'tiny-secp256k1';
const ECPair = ECPairFactory(ecc);
async function createInscription(
content: Buffer,
contentType: string,
feeRate: number, // sat/vByte
recipientAddress: string,
): Promise<{ commitTx: string; revealTx: string }> {
const keypair = ECPair.makeRandom({ network: bitcoin.networks.bitcoin });
// Строим envelope скрипт
const envelope = bitcoin.script.compile([
bitcoin.opcodes.OP_FALSE,
bitcoin.opcodes.OP_IF,
Buffer.from('ord'),
bitcoin.opcodes.OP_1,
Buffer.from(contentType),
bitcoin.opcodes.OP_0,
// данные разбиваются на чанки по 520 байт
...chunkData(content, 520),
bitcoin.opcodes.OP_ENDIF,
keypair.publicKey.slice(1), // x-only pubkey для Taproot
bitcoin.opcodes.OP_CHECKSIG,
]);
// Создаём P2TR output с инскрипцией в tapscript
const scriptTree = { output: envelope };
const p2tr = bitcoin.payments.p2tr({
internalPubkey: keypair.publicKey.slice(1),
scriptTree,
network: bitcoin.networks.bitcoin,
});
// Commit TX отправляет средства на p2tr.address
// Reveal TX тратит этот output, раскрывая скрипт
// ...
}
PSBT и подписание
Для пользовательских кошельков (Unisat, Xverse, OKX Wallet) транзакции строятся как PSBT (Partially Signed Bitcoin Transaction, BIP-174) и передаются кошельку на подписание:
const psbt = new bitcoin.Psbt({ network: bitcoin.networks.bitcoin });
psbt.addInput({
hash: utxo.txid,
index: utxo.vout,
witnessUtxo: {
script: p2tr.output!,
value: utxo.value,
},
tapLeafScript: [{
leafVersion: 0xc0,
script: envelope,
controlBlock: p2tr.witness![p2tr.witness!.length - 1],
}],
});
psbt.addOutput({
address: recipientAddress,
value: 546, // dust limit
});
// Сериализация для передачи в кошелёк
const psbtBase64 = psbt.toBase64();
Работа с существующими инскрипциями
Индексирование и поиск
Ordinals ord индексатор предоставляет JSON API (ord server):
# Инскрипции по адресу
GET /inscriptions/{address}
# Конкретная инскрипция
GET /inscription/{inscription_id}
# Sat с номером
GET /sat/{sat_number}
Для production с высокой нагрузкой: собственный индексатор поверх ord базы данных (SQLite или PostgreSQL миграция) + кэширование на Redis.
Трансфер инскрипций
Трансфер — обычная Bitcoin транзакция которая тратит UTXO содержащий инскрипцию. Критически важно: не смешивать обычные UTXOs с UTXOs-носителями инскрипций при формировании inputs транзакции — иначе инскрипция будет уничтожена (burned). Это называется inscription burning и происходит если inscribed sat попадает в позицию где ordinal theory считает его потраченным.
Правило безопасности: всегда проверять UTXO через ord API перед использованием как input.
Форматы и ограничения
Размер: теоретически до ~4MB (лимит блока), практически до ~380KB для надёжного включения в блок.
Content types: произвольный MIME-тип. Стандартные: image/png, image/webp, text/plain;charset=utf-8, application/json, text/html;charset=utf-8 (recursive inscriptions).
Recursive inscriptions: инскрипция может ссылаться на другую через /content/{inscription_id}. Используется для on-chain generative art.
BRC-20: JSON инскрипции со специальным форматом ({"p":"brc-20","op":"deploy",...}). Не валидируются нодой — только индексаторами. При разработке BRC-20 интеграции нужно понимать что консенсус по правилам — off-chain.
Стек и сроки
| Компонент | Технология |
|---|---|
| Нода | Bitcoin Core 26+ с txindex=1 |
| Ordinals индексатор | ord 0.18+ |
| Backend | TypeScript/Node.js + bitcoinjs-lib |
| Wallet интеграция | Unisat API / Xverse Provider API |
| Fee estimation | mempool.space API |
| База данных | PostgreSQL (метаданные) + Redis (кэш) |
Базовый сервис (минт + трансфер + просмотр коллекции): 3-4 недели. Поддержка BRC-20, recursive inscriptions, маркетплейс-функциональность — отдельная оценка.







