
Полная версия:
Введение в технологию Блокчейн
Таким образом, любая новая транзакция, которая попытается использовать выход с OP_RETURN, будет недействительной и не будет учитываться в блокчейне.
Независимо от того, какие значения вы ставите перед OP_RETURN, эта инструкция будет выполнена и скрипт вернет false.
Так как выбрасывается ошибка, данные в скрипте, которые появляются после OP_RETURN, не будут обрабатываться.
Таким образом, это также возможность помещать произвольные данные в скрипт и, следовательно, в цепочку блоков.
Если по какой-то причине вы хотите написать свое имя или хотите установить отметку времени и доказать, что знаете определенные данные в определенное время, тем самым, например, внести доказательство авторских прав на документ, вы можете создать транзакцию биткойнов с очень малой суммой и инструкцией OP_RETURN.
Вы можете уничтожить очень маленькую сумму валюты, но вы можете написать все, что захотите, в цепочку блоков, которая будет храниться всегда.
Теперь о скрипте Pay-to-script-hash.

Механизм работы скриптов Биткойна подразумевает, что отправитель монет должен точно указать скрипт.
Но это иногда становится затруднительным.
Скажем, например, вы являетесь покупателем интернет-магазина, и вы собираетесь что-то заказать.
И вы говорите: «Хорошо, я готов заплатить. Скажите мне адрес, на который я должен отправить свои монеты».
Теперь предположим, что компания, в которой вы заказываете товар, использует адрес MULTISIG с несколькими приватными ключами, то есть для их подписи используются несколько приватных ключей для дополнительной защиты.
Затем, так как вы должны указать это, продавец должен будет сказать вам: «Мы используем MULTISIG, и мы попросим вас отправить монеты с использованием сложного скрипта».
На что вы могли бы сказать: «Я не знаю, как это сделать. Это слишком сложно. Как потребитель, я просто хочу отправить монеты на простой адрес».
Для решения этой проблемы, в биткойне есть умный хак.
Вместо того, чтобы отправитель указывал весь скрипт, отправитель может указать только хэш скрипта, который понадобится для последующей траты этих монет.
Поэтому отправителю нужно просто указать очень простой скрипт, который просто хэширует верхнее значение в стеке и проверяет, соответствует ли оно требуемому скрипту траты монет.
Получателю этих монет необходимо указать в качестве значения данных, сам скрипт, чей хэш указан отправителем.
После этого произойдет второй этап проверки.
То есть, верхнее значение данных из стека будет переинтерпретировано в качестве инструкций, а затем оно будет выполняться во второй раз уже как скрипт.
Итак, мы видим, что здесь выполняются два этапа.
Сначала это был традиционный скрипт, который проверял, что скрипт потребления монет имеет правильный хеш.
И после этого скрипт потребления монет де-сериализуется и запускается как скрипт.
И вот где будет происходить фактическая проверка подписи.
Создание поддержки для этого типа скриптов P2SH было довольно сложным, поскольку этот тип скриптов не был частью первоначальной спецификации Bitcoin.
Он был добавлен позже.
Это, вероятно, самая известная функция, добавленная в биткойн, которой не было в исходной спецификации.
И она решает несколько важных проблем.
Она облегчает жизнь отправителю, так как получатель может просто указать хэш, на который отправитель отправляет деньги.
В нашем примере, Алисе не нужно беспокоиться о том, что Боб использует multisig, она просто отправляет деньги на адрес P2SH Боба, и ответственность Боба заключается в том, чтобы указать этот сложный скрипт, когда он хочет потратить монеты.
P2SH также ускоряет обработку.
Так, майнерам нужно отслеживать набор выходных скриптов, которые еще не были потрачены, а с P2SH выходные скрипты намного меньше, так как они указывают только хеш.
Вся сложность переносится на входные скрипты.
Теперь, когда мы понимаем, как работают скрипты Bitcoin, давайте взглянем на некоторые из применений, которые могут быть реализованы с помощью этого языка сценариев.
Оказывается, что мы можем делать много полезных вещей, которые оправдывают использование языка сценариев вместо того, чтобы просто указывать публичные ключи.
Рассмотрим транзакцию условного депонирования – это депонирование определенной суммы покупателем у третьего лица под определенные условия при сомнениях в добросовестности продавца.

Скажем, Алиса и Боб хотят вести дела друг с другом – Алиса хочет заплатить Бобу в Биткойнах, чтобы Боб отправил некоторый физический товар Алисе.
Проблема в том, что Алиса не хочет платить до тех пор, пока она не получит товар, а Боб не хочет отправлять товар до тех пор, пока он не будет оплачен.
Что мы можем с этим поделать?
Хорошим решением в биткойне, которое можно было бы использовать на практике, является введение третьей стороны и транзакция с депонированием.
Транзакция с депонированием может быть реализована достаточно просто с использованием мультиподписи MULTISIG.

Алиса не отправляет деньги непосредственно Бобу, а вместо этого создает транзакцию MULTISIG, для которой требуется два из трех человек, чтобы потратить монеты.
И эти три человека будут Алисой, Бобом, и некоторым сторонним арбитром Джуди, который вступит в игру, если возникнут какие-либо споры.
Поэтому, Алиса создает 2-из-3 транзакцию MULTISIG, которая отправляет некоторое количество монет, которыми она владеет, и указывает, что они могут быть потрачены, если будут две подписи из трех Алисы, Боба и Джуди.
Эта транзакция включена в цепочку блоков, и на данный момент эти монеты хранятся в депонировании между Алисой, Бобом и Джуди, так что любые два из них могут указать, куда должны уйти монеты.
В этот момент Боб убежден, что безопасно отправить товар Алисе, поэтому он отправит его по почте или каким-то другим способом.
Теперь, предположим, Алиса и Боб оба честны.
Поэтому Боб отправит товар, который ожидает Алиса, и когда Алиса получит товар, Алиса и Боб подпишут транзакцию, потратив средства из депонирования и отправив их Бобу.
Обратите внимание, что в этом случае, когда Алиса и Боб честны, Джуди не нужно вмешиваться.
Не было никакого спора, и подписи Алисы и Боба соответствовали требованию 2-из-3 транзакции MULTISIG.
Так что в нормальном случае это ничем не отличается, как если бы Алиса просто отправила бы Бобу деньги, но это требует одной дополнительной транзакции.
Но что могло бы произойти, если бы Боб не отправил товар или товар потерялся бы на почте?
Или, может быть, товар отличался бы от того, который заказывала Алиса?
Алиса теперь не хочет платить Бобу, потому что думает, что ее обманули, и она хочет вернуть свои деньги.
Поэтому Алиса определенно не собирается подписывать транзакцию, которая передает деньги Бобу.
Но Боб также может отрицать любые нарушения и отказываться подписывать транзакцию, которая возвращает деньги Алисе.
Здесь необходимо принять участие Джуди.

Джуди придется решить, кто из этих двух людей заслуживает денег.
Если Джуди решит, что Боб обманул, Джуди подпишет сделку вместе с Алисой, отправив деньги с эсквота обратно Алисе.
Подписи Алисы и Джуди отвечают требованиям 2-из-3 транзакции MULTISIG, и Алиса вернет себе деньги.
И, конечно, если Джуди думает, что здесь виновата Алиса, и Алиса просто отказывается платить, Джуди может подписать транзакцию вместе с Бобом, отправив деньги Бобу.
Поэтому в этом случае Джуди решает, какой будет результат.
Но ей не придется участвовать, если нет спора.
Еще одно интересное применение скриптов – это то, что называют зелеными адресами.
Предположим, Алиса хочет заплатить Бобу, но Боб не в сети.
Так как он не в сети, Боб не может взять и посмотреть на цепочку блоков, чтобы увидеть, находится ли там транзакция, которую послала Алиса.
Также возможно, что Боб находится в сети, но у него нет времени, чтобы посмотреть на цепочку блоков и дождаться подтверждения транзакции.
Помните, что обычно мы ждем, чтобы транзакция попала в цепочку блоков и была подтверждена шестью последующими блоками, что занимает около часа, прежде чем мы будем уверены, что транзакция действительно находится в цепочке блоков.
Но для некоторых товаров, таких как еда, Боб не может ждать час, чтобы начать доставку.
Если бы Боб был уличным продавцом, продающим хот-доги, маловероятно, что Алиса будет ждать около часа, чтобы получить еду.
Или, возможно, Боб по какой-либо другой причине вообще не имеет никакого подключения к Интернету и, следовательно, не сможет проверить цепочку блоков.
Чтобы решить эту проблему, чтобы вы могли отправлять деньги с помощью биткойна, не получая доступ к блокчейну, мы должны предоставить другую третью сторону, которую мы будем называть банком (на практике это может быть любой финансовый посредник).

Тогда Алиса связывается с ее банком и говорит: «Это я, Алиса. Я твой лояльный клиент. Вот моя карточка или мой идентификатор. И я бы хотела заплатить Бобу, не могли бы вы мне помочь?»
На что банк говорит: «Конечно. Я спишу эту сумму с вашего счета. И составлю транзакцию с одного из моих зеленых адресов на Боба».
Поэтому обратите внимание, что эти деньги поступают напрямую от банка к Бобу.
Какая-то сумма, конечно, может быть в обратном адресе, возвращающемся в банк.
Но, по сути, банк платит Бобу с банковского адреса, который мы называем зеленым адресом.
Более того, банк гарантирует, что он не будет дважды тратить эти деньги.
И, как только Боб видит, что эта транзакция подписана банком, если он доверяет гарантии банка не делать двойную трату этих денег, он может заранее принять то, что в конечном итоге это будут его деньги, когда транзакция будет подтверждена в цепочке блоков.
Обратите внимание, что это не гарантия, основанная на биткойнах.
Это реальная гарантия, и для того, чтобы эта система работала, Боб должен верить, что банк в реальном мире заботится о своей репутации и не будет по этой причине делать двойные траты.
И банк сможет сказать: «Вы можете посмотреть на мою историю. Я давно использую этот зеленый адрес, и я никогда не совершал по нему двойной траты. Поэтому я вряд ли сделаю это в будущем».
Таким образом, Бобу больше не нужно думать о доверии Алисе, о которой он ничего не знает.
Вместо этого он доверяет банку, что они не будут дважды тратить деньги, которые они ему отправили.
Конечно, если банк когда-либо сделает двойную трату, люди перестанут доверять этим зеленым адресам.
Фактически, двумя наиболее известными онлайн-службами, которые реализовали зеленые адреса, были Instawallet и Mt. Gox, и обе в итоге закрылись, так как совершили двойную трату.
Сегодня зеленые адреса практически не используются.
Когда идея была впервые предложена, она привлекла внимание как способ сделать платежи быстрее и без доступа к цепочке блоков.
Затем, однако, люди разочаровались в ней по причине того, что она требует слишком большого доверия банку.

Третий пример применения скриптов биткойнов – это способ совершать эффективные микроплатежи.
Предположим, что Алиса – клиент, который хочет постоянно платить Бобу небольшую сумму денег за некоторую услугу, которую предоставляет Боб.
Например, Боб может быть поставщиком услуг мобильной связи для Алисы, и требует, чтобы она платила небольшую плату за каждую минуту, которую она проговорила со своего телефона.
Создание транзакции биткойнов для каждой минуты, которую Алиса проговорит по телефону, не будет работать.
Это создаст слишком много транзакций с комиссией за каждую транзакцию.
Поэтому, учитывая комиссию за каждую транзакцию, плата Алисы за услуги будет слишком высокой.
Поэтому нам хотелось бы, чтобы все эти небольшие платежи были объединены в один большой платеж в конце.
Оказывается, существует приемлемый способ это сделать.
Мы начинаем с транзакции, которая платит максимальную сумму на адрес MULTISIG, сумму которую Алисе когда-либо потребуется потратить, и этот адрес MULTISIG требует подписи как Алисы, так и Боба, чтобы разблокировать эти монеты.
Теперь, после первой истраченной минуты, когда Алиса использовала услугу, или, когда в первый раз Алисе нужно сделать микроплатеж, она подписывает транзакцию, тратя те монеты, которые были отправлены на адрес MULTISIG, отправляя одну единицу платежа Бобу и возвращая остальные монеты Алисе. После следующей использованной минуты Алиса подписывает еще одну транзакцию, на этот раз отдавая Бобу две единицы и отправляя остальную часть себе.
Обратите внимание, что эти транзакции подписаны только Алисой и еще не подписаны Бобом, и они не публикуются в блокчейне.
И Алиса будет продолжать отправлять эти транзакции Бобу каждую минуту, когда она использует эту услугу.
В конце концов, Алиса закончит использовать эту услугу и сообщит Бобу: «Я закончила, пожалуйста, прекратите мое обслуживание».
В этот момент Алиса прекратит подписывать дополнительные транзакции.
Услышав это, Боб скажет: «Отлично. Я отключаю ваш сервис, и я беру последнюю транзакцию, которую вы прислали мне, подписываю ее, и публикую ее в цепочке блоков».
Таким образом, последняя транзакция, которую Боб подписывает, выплачивает ему полностью за предоставленную им услугу и возвращает остальную часть денег Алисе.
Все эти промежуточные транзакции, подписанные Алисой, не попадут в цепочку блоков. И Бобу не нужно их подписывать. Они просто будут отброшены.
Технически все эти транзакции подразумевают возможность двойной траты.
Таким образом, в отличие от случая с зелеными адресами, где мы специально пытались избежать двойных трат с большой гарантией, в этом протоколе микроплатежей, мы фактически генерируем огромное количество потенциальных двойных трат.
На практике, однако, если обе стороны работают нормально, Боб никогда не будет подписывать какую-либо транзакцию, кроме последней, и в этом случае блокчейн фактически не увидит попыток двойной траты.
Здесь есть еще одна сложность: что, если Боб никогда не подпишет последнюю транзакцию?
Он может просто сказать: «Я хочу, чтобы монеты находились на депонировании навсегда», и в этом случае, монеты не будут расходоваться, но при этом Алиса может потерять сдачу или остаток монет, который она расчитывала получить обратно.
Существует очень умный способ избежать этой проблемы, используя функцию, о которой мы упоминали ранее.

Чтобы избежать этой проблемы, прежде чем начнется протокол микроплатежей, Алиса и Боб оба подпишут транзакцию, которая вернет все деньги Алисы, но возврат будет «заблокирован» до определенного момента времени в будущем.
Поэтому после того, как Алиса подпишет, но прежде чем она транслирует первую транзакцию MULTISIG, которая вложит ее средства в депонирование, она получит эту возвратную транзакцию от Боба и будет удерживать ее.
Это гарантирует, что, если до определенного момента времени Боб не подпишет ни одной из небольших транзакций, которые отправила Алиса, Алиса может опубликовать эту транзакцию, которая вернет все деньги непосредственно ей.
Что это значит, что транзакция заблокирована до определенного момента времени?
Вспомните, когда мы смотрели на метаданные в транзакциях биткойнов, там был параметр lock_time, который мы оставили без рассмотрения.
Он работает следующим образом.
Если вы укажете любое значение, отличное от нуля, представляющее время блокировки, это значение сообщает майнерам не публиковать транзакцию до указанного момента времени, или пока определенное количество блоков не будет внесено в блокчейн.
Locktime представляет собой четырехзначное целое число без знака, которое можно обработать двумя способами:
Если это число меньше 500 миллионов, Locktime интерпретируется как высота блока, то есть количество блоков в блокчейне от нулевого до последнего блока.
Транзакция может быть добавлена в любой блок с этой высотой или выше.
Если значение больше или равно 500 миллионам, Locktime интерпретируется с использованием формата времени эпохи Unix (количество секунд, прошедших с 1970-01-01T00: 00 UTC, в настоящее время превышает 1.395 миллиардов).
Транзакция может быть добавлена в любой блок по прошествии этого времени.
Также есть много других примеров использования биткойн скриптов, которые были предложены.
Одно из применений – это многопользовательские лотереи с очень сложным многоступенчатым протоколом с множеством транзакций, имеющих депонирование и разные времена блокировки.
Существуют также некоторые протоколы, в которых используется язык скриптов, позволяющие разным людям объединять свои монеты и смешивать их, так что сложнее проследить, кому принадлежит монеты. Мы рассмотрим это подробнее позже.
Общий термин для протоколов, подобных тем, которые мы рассмотрели, является умные контракты или смарт контракты.
Это контракты, которые традиционно обеспечиваются с помощью законов или арбитражных судов, но для реализации которых у нас есть определенная степень технического обеспечения в Биткойне.
Это замечательная функция Bitcoin, где мы можем использовать скрипты, майнеров и проверку транзакций для реализации, например, протокола депонирования или протокола микроплатежей, не требующих централизованного управления.
Также существует много типов смарт контрактов, которые люди хотели бы использовать, но которые на сегодняшний день не поддерживаются языком скриптов Bitcoin.
Или, по крайней мере, никто не придумал способ их реализации.
Блоки Bitcoin
До сих пор мы рассматривали, как создаются и потребляются отдельные транзакции.
Но, как мы видели раньше, транзакции сгруппированы в блоки.
Зачем это нужно?
В принципе, это ничто иное как оптимизация.
Если бы майнеры должны были бы приходить к консенсусу по каждой транзакции отдельно, скорость, с которой новые транзакции принимались бы системой, была бы намного ниже.
Кроме того, хеш-цепочка блоков намного короче, чем хеш-цепочка транзакций, поскольку в каждый блок может быть помещено большое количество транзакций.
Это позволяет повысить эффективность проверки структуры цепочки блоков.
Каждый блок должен включать одну или несколько транзакций.
Первая из этих транзакций должна быть транзакцией coinbase или транзакцией генерации, которая собирает и тратит вознаграждение за блок, состоящее из вознаграждения за сам блок и любых транзакционных сборов, оплаченных транзакциями, включенными в этот блок.
Цепочка блоков – это умная комбинация двух разных структур данных на основе хэшей.

Первая структура – это хеш-цепочка блоков.
Каждый блок имеет заголовок блока с хэш-указателем на транзакции и хэш-указателем на предыдущий блок в последовательности.
Вторая структура данных – это дерево всех транзакций для каждого блока, которые включены в этот блок.
Все транзакции, включая транзакцию coinbase, кодируются в блоке в бинарном формате.
Этот формат хэшируется для создания идентификатора транзакции.
Из этих идентификаторов строится дерево merkle путем спаривания каждого идентификатора с одним другим идентификатором и последующим их объединением.
Если существует нечетное число идентификаторов, идентификатор без партнера хешируется с копией самого себя.
Затем результирующие хеши объединяются по парам и хэшируются вместе.
Любой хеш без партнера хэшируется сам с собой.
Процесс повторяется до тех пор, пока не останется только один хеш, или корень merkle.
Таким образом, это дерево Merkle позволяет нам иметь дайджест всех транзакций в блоке эффективным образом.
Как мы видели ранее, чтобы доказать, что транзакция включена в конкретный блок, мы можем предоставить путь через дерево, длина которого – это логарифм числа транзакций в блоке.
Для повторения, блок состоит из заголовка с данными, за которыми следует список транзакций, расположенных в древовидной структуре.
Заголовок блока содержит информацию, связанную с майнингом.

Вспомните, что хеш заголовка блока должен начинаться с большого количества нулей для того, чтобы блок был действительным.
Доказательство работы подразумевает, что хэш заголовка блока должен быть меньше указанного.
Другой способ сказать это, что хэш заголовка блока должен начинаться с определенного количества нулей.
Любой блок, заголовок которого не создает хэш, который меньше целевого значения, будет отклонен сетью.
Целевое значение настраивается каждые две недели, чтобы поддерживать среднее время создания нового блока 10 минут.
Заголовок также содержит значение «nonce», которое изменяется майнером, чтобы хэш заголовка блока был меньше целевого значения.
Заголовок содержит отметку времени и целевое значение, которое определяет трудность нахождения этого блока.
Таким образом, если после того, как вы обработали каждую транзакцию и нашли корень дерева Merkle, добавили его в заголовок блока с хешем предыдущего блока и nonce, хэшировали заголовок и создали значение, которое с правильным количеством нулей не попадает в указанный целевым значением диапазон, тогда изменяется значение nonce, заголовок блока снова хэшируется и так до тех пор, пока хэш заголовка блока не будет меньше целевого значения.
Заголовок – это единственное, что хэшируется во время майнинга.
Чтобы проверить цепочку блоков, нам нужно только посмотреть на заголовки.
Единственными данными транзакций, включенными в заголовок, является корень дерева транзакций – поле «mrkl_root».

Как я уже сказал, блок содержит специальную транзакцию в дереве Merkle, называемую транзакцией «coinbase».
Здесь происходит создание новых монет в Биткойне.
Эта транзакция выглядит как обычная транзакция, но имеет несколько отличий:
Она всегда имеет один вход и один выход, при этом вход не тратит предыдущий выход и, следовательно, содержит нулевой хэш указатель, так как он чеканит новые биткойны и не тратит существующие монеты.
Также стоимость выхода в настоящее время составляет около 6,25 биткойнов.
Выходное значение – это доход майнера от блока.
Оно состоит из двух компонентов: награды за добычу блока, которая устанавливается системой, и которая делится пополам каждые 210 000 блоков (около 4 лет) и комиссионных сборов, взимаемых с каждой транзакции, включенной в блок.
Также coinbase транзакция содержит специальный параметр coinbase, который абсолютно произволен – майнеры могут записывать туда все, что захотят.
Известно, что в самом первом блоке, добытом в Биткойне, параметр coinbase ссылался на историю в газете Times of London, в которой участвовал канцлер, спасающий банки.
Это интерпретировалось как политический комментарий о мотивации для запуска биткойн.
Это также служит доказательством того, что первый блок был добыт после того, как газета вышла 3 января 2009 года.
Также параметр coinbase может использоваться для уведомления майнерами о поддержке различных новых функций.
Чтобы лучше понять формат блока и формат транзакции, лучше всего изучить цепочку блоков.
Есть много веб-сайтов, которые делают эти данные доступными, например, blockchain.info.

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