Добавить в цитаты Настройки чтения

Страница 15 из 27

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

Это позволяет ему консолидировать эти две транзакции.

Также, легко сделать и совместные платежи.

Предположим, Кэрол и Боб оба хотят заплатить Дэвиду.

Они могут создать транзакцию с двумя входами, которые принадлежат разным людям, и одним выходом.

И единственное отличие от предыдущего примера состоит в том, что, поскольку два выхода из предыдущих транзакций, которые здесь заявляются, относятся к разным адресам, для новой транзакции потребуется две отдельные подписи: одна – Кэрол, а другая – Боба.

Концептуально это все, что связано с транзакцией биткойнов.

Теперь посмотрим, как она представлена на низком уровне в биткойне.

В конечном счете, каждая структура данных, которая отправляется в сеть, представляет собой строку бит.

То, что здесь показано, является низкоуровневым форматом, но далее это дополнительно компилируется до компактного двоичного формата, который не читается человеком.

Как вы можете видеть в этом примере, транзакция делится на три части: некоторые метаданные, серия входов и серия выходов.

Что качается метаданных, здесь есть некоторая информация о самой транзакции – размер транзакции, количество входов и количества выходов.

Также здесь указан хэш всей транзакции, который служит уникальным идентификатором транзакции.

Это позволяет нам использовать хеш-указатели для ссылок на транзакции.

Наконец, есть поле «lock_time», к которому мы вернемся позже.

Теперь о входах.

Входы транзакций образуют массив, и каждый вход имеет один и тот же формат.

Вход указывает предыдущую транзакцию с помощью хэша этой транзакции, который работает как хэш-указатель на предыдущую транзакцию.

Вход также содержит индекс выхода предыдущей транзакции, на которую идет ссылка.

И здесь еще есть подпись.

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

Теперь о выходах.

Выходы также представляют собой массив.

Каждый выход имеет только два поля. У каждого выхода есть значение, а сумма всех выходных значений должна быть меньше или равна сумме всех входных значений.

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

Также, у выхода есть строка, которая выглядит как адрес получателя.

Мы видим, что здесь есть хэш публичного ключа, а также есть набор команд.

Так что это поле на самом деле является скриптом.

Bitcoin скрипты

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

На самом деле он определяет скрипт.

Что такое скрипт и почему мы используем скрипты?

Далее мы рассмотрим язык Bitcoin скриптов и поймем, почему скрипт используется вместо простого указания открытого ключа.

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

В этом случае мы хотим, чтобы на выходе транзакции говорилось: «этот выход транзакции может быть потрачен с помощью подписи следующего владельца указанного адреса.»

Напомним, что адрес является хешем публичного ключа.



Поэтому просто указание адреса не дает нам публичный ключ, и не дает нам возможности проверить подпись!

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

Теперь, что происходит с этим скриптом?

Кто его запускает, и как именно эта последовательность инструкций обеспечивает соблюдение вышеуказанного утверждения?

Секрет в том, что входы также содержат скрипты вместо просто подписей.

Чтобы проверить, что новая транзакция правильно потребляет выход предыдущей транзакции, мы объединяем входной скрипт новой транзакции и выходной скрипт предыдущей транзакции.

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

Эти два скрипта называются scriptPubKey и scriptSig, потому что в простейшем случае выходной скрипт просто указывает хэшированный публичный ключ или адрес, который может потребить этот выход транзакции, а входной скрипт следующей транзакции указывает подпись с этим публичным ключом.

Bitcoin язык скриптов был создан специально для биткойнов и называется просто «Скрипт».

Он имеет много общего с языком под названием Forth, который является старым, простым, основанным на стеках языком программирования.

Но вам не нужно изучать Форт, чтобы понимать скрипты биткойнов.

Язык Script был создан, чтобы иметь что-то простое и компактное, но с собственной поддержкой криптографических операций.

Поэтому в нем существуют специальные инструкции для вычисления хеш-функций, а также для вычисления и проверки подписей.

Язык Script основан на стеках.

Это означает, что каждая инструкция выполняется ровно один раз, линейно.

В частности, в языке Script биткойнов нет циклов.

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

Этот язык не имеет возможности вычислять произвольно мощные функции.

И по замыслу, именно майнеры должны запускать эти скрипты, которые предоставляются произвольными участниками сети.

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

Таким образом, чтобы проверить, правильно ли новая транзакция потребляет выход предыдущей транзакции, мы создаем комбинированный скрипт, добавляя скрипт scriptPubKey предыдущей транзакции снизу к скрипту scriptSig новой транзакции.

Обратите внимание, что <pubKeyHash?> содержит ?'.

Мы используем это обозначение, чтобы указать, что мы позже проверим, что это значение равно хешу публичного ключа, который предоставлен во входном скрипте.

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

Он либо успешно выполняется без ошибок, и в этом случае транзакция действительна.

Или, если во время выполнения скрипта есть какая-либо ошибка, тогда вся транзакция будет недействительной и не должна приниматься в цепочку блоков.

Язык скриптов биткойнов очень маленький.

В нем есть только 256 инструкций, и каждая из них представлена одним байтом.

Байт состоит из восьми бит. Используя один байт, можно закодировать один символ из 256 возможных (256 = 2 в 8 степени). Таким образом, один байт равен одному символу, то есть 8 битам.

Из этих 256 инструкций, 15 в настоящее время отключены, и 75 зарезервированы.

Зарезервированные инструкции еще не получили никакого специального значения.

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

Там есть базовая арифметика, базовая логика, такая как ‘if’ и ‘then, выброс ошибки, возврат return.

Наконец, существуют криптографические инструкции, которые включают хеш-функции, инструкции для проверки подписи, а также специальную и важную инструкцию CHECKMULTISIG, которая позволяет проверять несколько подписей в одной инструкции.