Peer-to-Peer / Bitcoin: встроенная система сценариев и цифровые контракты

в 13:06, , рубрики: bitcoin, cryptography, p2p, метки: , ,

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

В этом же посте затронут весьма узкий аспект — встроенная система сценариев, предназначенная для проверки валидности транзакций, а также некоторые её возможности. На родном языке такой информации мне не попадалось, потому вношу свою лепту.

Немного о сценариях

Для проверки транзакций Bitcoin имеется встроенный стек-ориентированный язык сценариев, чем-то похожий на Forth. По понятным причинам он не является Тьюринг-полным и в нём нет циклов. С другой стороны, он очень прост.

По существу, сценарий — это последовательность инструкций внутри транзакции, которая описывает, как лицо, желающее потратить биткоины, должно получить к ним доступ. Сценарий типичного перевода средств на адрес A налагает 2 требования на лицо, желающее впоследствии воспользоваться этими средствами:

  • предоставить в следующей транзакции открытый ключ, хэш которого равен A,
  • предоставить подпись, доказывающую владение указанным выше открытым ключом.

Сценарии достаточно гибки по части указания различных условий дальнейшего распоряжения средствами. Например, можно потребовать два ключа/подписи или комбинацию нескольких подписей. В общем случае лицо(лица), отправляющее средства, указывает в транзакции сценарий их последующей траты (scriptPubKey). Лицо(лица), желающее воспользоваться полученными средствами, в следующей транзакции указывает входные данные для сценария (scriptSig). Если у транзакции сумма входящих средств больше или равна сумме исходящих средств, а комбинированный (scriptSig + scriptPubKey) сценарий выполняется без сбоя и в результате его работы на верхушке стека оказывается истинное (ненулевое) значение, транзакция считается валидной и майнеры могут включать её в цепочку блоков.

Пример типичной транзакции:

scriptPubKey:
OP_DUP OP_HASH160 {addr} OP_EQUALVERIFY OP_CHECKSIG

scriptSig:
{sig} {pubKey}

Трассировка по шагам:

Стек Сценарий
0 EMPTY {sig} {pubKey} OP_DUP OP_HASH160 {addr} OP_EQUALVERIFY OP_CHECKSIG
1 {sig} {pubKey} OP_DUP OP_HASH160 {addr} OP_EQUALVERIFY OP_CHECKSIG
2 {sig} {pubKey} OP_DUP OP_HASH160 {addr} OP_EQUALVERIFY OP_CHECKSIG
3 {sig} {pubKey} {pubKey} OP_HASH160 {addr} OP_EQUALVERIFY OP_CHECKSIG
4 {sig} {pubKey} {hash} {addr} OP_EQUALVERIFY OP_CHECKSIG
5 {sig} {pubKey} {hash} {addr} OP_EQUALVERIFY OP_CHECKSIG
5 {sig} {pubKey} OP_CHECKSIG
6 TRUE EMPTY

Подробнее про сценарии можно почитать здесь.

Временная блокировка, мультиверсионность и прочая магия

Помимо сценариев в Bitcoin-транзакциях есть еще несколько интересных штук: транзакция может быть отложенной на некоторое время или до какого-то конкретного блока, может менять в процессе согласования свою версию. У обычных транзакций интервал блокировки равен нулю, а версия — максимально возможная.

Кроме того, имеется возможность задавать режим хеширования транзакции при проверке подписи:

  • SIGHASH_ALL — режим по умолчанию, по сути означает «я вношу свою часть если каждый вносит свою и получатели денег такие-то каждый на соответствующую сумму»;
  • SIGHASH_NONE — означает «я вношу свою часть если каждый вносит свою, а кто получатель мне все равно»;
  • SIGHASH_SINGLE — почти то же самое, по сути «я вношу свою часть если каждый вносит свою, но один из получателей такой-то на такую-то сумму».

Есть еще модификатор SIGHASH_ANYONECANPAY, который, будучи добавленным к любому из перечисленных режимов, по сути уберет слова «если каждый вносит свою» из описаний этих самых режимов.

Контракты

И вот на таком хитром базисе можно строить распределенные контракты — метод достижения договорённости между сторонами посредством использования цепочки блоков. Контракты не делают чего-то такого, что не было бы возможно раньше, однако они позволяют решать некоторые распространенные проблемы таким образом, что не требуется взаимного доверия сторон или его уровень сведен к минимуму. Такой подход позволяет избавиться от услуг доверенного посредника (который может прихватить ваши денежки и быть таков) при совершении сделок и разрешении спорных ситуаций. В качестве примера рассмотрим следующую жизненную ситуацию.

Сделка с протекцией и разрешение конфликта

Покупатель желает приобрести товар у продавца, которого он не знает и которому не доверяет. В случае нормально прошедшей сделки покупатель не хотел бы посвящать в детали постороннее лицо. Однако в случае проблем покупатель хотел бы, чтобы независимый арбитр решил, кто получит деньги. В качестве доказательства последний может запросить у продавца, скажем, квитанцию об отправке товара почтой.

Другими словами, Покупатель хотел бы заблокировать некую сумму, распоряжаться которой можно было бы с согласия хотя бы двух лиц из трех. Для этого он:

  • Договаривается с Продавцом об Арбитре.
  • Запрашивает у Продавца и Арбитра их открытые ключи K1 и K2 соответственно и создает новый ключ K3 для себя.
  • Посылает продавцу ключ Арбитра K2. Продавец проверяет подлинность K2 запросив подпись случайного числа.
  • Создает транзакцию T1 на сумму заказа такую, что потратить ее исходящие средства можно только по предоставлении хотя бы 2 подписей, и публикует ее в сети.

После включения транзакции в цепочку блоков средства могут быть потрачены транзакцией T2 если:

  • Покупатель и Продавец ставят свои подписи под ней — сделка завершилась успешно или Продавец возвратил средства клиенту не дожидаясь решения Арбитра.
  • Покупатель и Арбитр ставят свои подписи — сделка не произошла, Арбитр вернул средства Покупателю.
  • Арбитр и Продавец ставят свои подписи — сделка признана Арбитром состоявшейся, несмотря на возражения Покупателя, средства переданы продавцу.

Подробнее о контрактах можно почитать здесь и здесь. Если тема будет интересной, опишу еще несколько типовых контрактов.

Автор: vibornoff

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js