Техническая Документация Tezos

Содержание

Введение

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

Самообновляющийся крипто-леджер

Протокол блокчейна можно разбить на три отдельных протокола:

  • Сетевой протокол, обнаруживающий блоки и транслирующий транзакции.

  • Протокол транзакции, определяющий, что делает транзакцию действительной.

  • Протокол консенсуса, формирующий консенсус вокруг уникальной цепи.

Tezos внедряет универсальную сетевую оболочку. Эта оболочка не зависит от протокола транзакций и протокола консенсуса. Вместе протокол транзакций и протокол консенсуса мы называем «протоколом цепи блоков». Сначала мы представим математическое представление протокола блокчейна, а затем опишем некоторые варианты реализации в пределах Tezos.

Математическое представление

Протокол блокчейна по сути является монадической реализацией параллельных мутаций глобального состояния. Это достигается путем определения «блоков» как операторов, воздействующих на это глобальное состояние. Свободный моноид блоков, работающих в соответствии с состоянием происхождения, образует древовидную структуру. Глобальное каноническое состояние определяется как минимальный лист для указанного порядка (расположения).

Исходя из вышесказанного, получим следующее абстрактное представление:

  • Let $(\mathbf{S},\leq)$ полностью упорядоченный, исчисляемый набор возможных состояний.

  • Let $\oslash \notin \mathbf{S}$ представляет особое, недействительное состояние.

  • Let $\mathbf{B} \subset \mathbf{S}^{\mathbf{S} \cup {\oslash}}$ - набор блоков. Набор действительных блоков: $\mathbf{B} \cap \mathbf{S}^{\mathbf{S}}$.

Общий порядок на $\mathbf{S}$ расширен до $\forall s \in \mathbf{S}, \oslash < s$. Этот порядок определяет, какой лист в дереве блоков будет считаться каноническим. Блоки в $\mathbf{B}$ рассматриваются как операторы, воздействующие на данное состояние.

Подводя итог изложенному выше, отметим следующее: любой блокчейн-протокол1 (будь то Bitcoin, Litecoin, Peercoin, Ethereum, Cryptonote и т.д.) может быть полностью определен кортежем:

По большому счёту, сетевой протокол идентичен для этих блокчейнов. Алгоритмы «майнинга» - лишь независимое свойство сети, учитывая стимулы для создания блоков.

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

Сетевая оболочка

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

Сетевая оболочка работает, поддерживая лучшую из известных клиенту цепей. Ей известны три типа объектов. Первые два - это транзакции и блоки, которые распространяются через сеть только в том случае, если они считаются действительными. Третьим являются протоколы и модули OCaml, используемые для изменения существующего протокола. Их подробное описание будет приведено ниже. А пока мы сосредоточимся на транзакциях и блоках.

Наиболее сложной частью работы сетевой оболочки является защита узлов от атак типа «отказ в обслуживании».

Частота

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

Алгоритм выбора цепи

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

Содержание дерева было бы более экономичным с точки зрения сетевых коммуникаций, но восприимчивым к атакам типа Denial-of-Service («отказ в обслуживании»), когда злоумышленник производит большое количество слабых, но действительных вилок.

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

К счастью, протокол может обладать тем свойством, что цепочки с низким показателем демонстрируют низкую скорость создания блоков. Таким образом, клиент будет рассматривать только несколько блоков «слабого» форка, прежде чем придет к выводу, что объявленный счёт является ложным.

Защита на уровне сети

Кроме того, оболочка является «защитной». Она пытается подключиться к множеству узлов через различные диапазоны IP-адресов. Оболочка обнаруживает отключенные узлы и блокирует вредоносные ноды.

Для защиты от определенных атак типа «Отказ в обслуживании» протокол предоставляет оболочке контекстно-зависимые предельные значения для размера блоков и транзакций.

Функциональное представление

Валидация цепи

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

type raw_block_header = {
pred: Block_hash.t;
header: Bytes.t;
operations: Operation_hash.t list;
timestamp: float;
}

Мы намеренно не вводим поле заголовка сильнее, чтобы оно могло представлять произвольный контент. Однако мы вводим поля, необходимые для работы оболочки. К ним относятся хэш предыдущего блока, список хэшей операций и временная метка. На практике операции, включенные в блок, передаются вместе с блоками на уровне сети. Сами операции представлены в виде произвольных BLOB-объектов.

type raw_operation = Bytes.t

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

module Context = sig
type t
type key = string list
val get: t -> key -> Bytes.t option Lwt.t
val set: t -> key -> Bytes.t -> t Lwt.t
val del: t -> key -> t Lwt.t
(*...*)
end

Во избежание блокировки дисковых операций, функции используют асинхронную монаду Lwt [@LWT]. Обратите внимание, что операции над контекстом зачастую являются функциональными: get использует option monad вместо того, чтобы выдавать исключение, в то время как set и del возвращают новый Context. Модуль Context использует комбинацию кэширования памяти и дискового хранилища, чтобы эффективно представить неизменяемое хранилище.

Теперь мы можем определить тип модуля произвольного блокчейн-протокола:

type score = Bytes.t list
module type PROTOCOL = sig
type operation
val parse_block_header : raw_block_header -> block_header option
val parse_operation : Bytes.t -> operation option
val apply :
Context.t ->
block_header option ->
(Operation_hash.t * operation) list ->
Context.t option Lwt.t
val score : Context.t -> score Lwt.t
(*...*)
end

Мы больше не сравниваем состояния напрямую, как в математической модели. Вместо этого проецируем Context на список байтов, используя функцию Score. Список байтов упорядочен сначала по длине, затем - по лексикографическому порядку. Это относительно универсальная структура, похожая на ту, что используется при управлении версиями ПО, которая считается довольно гибкой если речь идет о представлении различных упорядочений.

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

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

Функция apply является основой протокола:

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

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

Внесение изменений в протокол

Самая мощная особенность Tezos - возможность реализовывать протокол, способный к самоизменению. Это достигается путем предоставления протоколу двух процедурных функций:

  • set_test_protocol которая заменяет протокол, используемый в тестовой сети, новым протоколом (обычно протоколом, принятым голосующим стейкхолдером).

  • promote_test_protocol которая заменяет текущий протокол на протокол, который в настоящее время тестируется.

Эти функции преобразуют Context, изменяя связанный протокол. Новый протокол вступает в силу, когда к цепи применяется следующий блок.

module Context = sig
type t
(*...*)
val set_test_protocol: t -> Protocol_hash.t Lwt.t
val promote_test_protocol: t -> Protocol_hash.t -> t Lwt.t
end

protocol_hash - это хэш sha256 из тарболла файлов .ml и .mli. Данные файлы компилируются на лету. Они имеют доступ к небольшой стандартной библиотеке, но находятся в песочнице и могут не выполнять никаких системных вызовов.

Эти функции вызываются через функцию apply, которая возвращает новый Context.

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

RPC

Чтобы упростить работу по созданию графического интерфейса, протокол предоставляет API-интерфейс JSON-RPC. Сам API описывается схемой json, указывающей типы различных процедур. Как правило, такие функции, как get_balance, могут применяться в RPC.

type service = {
name : string list ;
input : json_schema option ;
output : json_schema option ;
implementation : Context.t -> json -> json option Lwt.t
}

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

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

Сам пользовательский интерфейс может быть адаптирован к конкретной версии протокола или в целом получен из спецификации JSON.

Seed протокол

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

Экономика

Коины

Предлагаем, чтобы одна монета называлась « tez», а самая маленькая единица - просто цент. Также предлагаем использовать символ ꜩ (\ua729, «латинская маленькая буква tz») для обозначения теза (tez). В ходе сбора средств в общей сложности было сгенерировано 763,306,929.69 ꜩ, которые были распределены среди участников сбора.

Вознаграждения за майнинг и подписание

Принцип

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

Облигации представляют собой 5-цикловые гарантийные вклады, приобретаемые майнерами и индоссантами. В случае двойной подписи эти облигации утрачиваются.

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

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

Особенности

В seed протоколе майнинг блока предлагает вознаграждение в размере 16 ꜩ и требует наличие облигации в размере 512 ꜩ за каждый созданный блок. Подписание блока предлагает вознаграждение до 2 ꜩ в зависимости от приоритета созданного блока. В каждом блоке может быть до 32 подписей, а для подписи требуется залог в 64 ꜩ.

График вознаграждений предполагает номинальный уровень инфляции в 5,5%. Номинальная инфляция нейтральна: она никого не обогащает и не обедняет2.

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

Потерянные коины

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

Правила внесения правок

Поправки принимаются избирательными циклами продолжительностью $N = 2^{17} = 131072$ блоков каждый. Учитывая интервал блокировки в одну минуту, это около трех календарных месяцев. Избирательный цикл сам по себе делится на четыре четверти $2^{15} = 32768$ блоков. Этот цикл является относительно коротким, чтобы способствовать ранним улучшениям, но ожидается, что дальнейшие поправки увеличат его продолжительность. С целью обеспечения быстрой итерации, голосование за обновление протокола в первый год будет более частым. В качестве меры безопасности Tezos Foundation будет обладать правом вето, срок действия которого истекает через двенадцать месяцев, пока мы не исключим какие-либо отклонения в процедуре голосования. Утверждение требует определенного кворума. Этот кворум начинается с $Q = 80\%$, но динамически адаптируется для отражения среднестатистического участия. Это необходимо только в случае с потерянными коинами.

Первый квартал

Изменения протокола предлагаются путем отправки хэша тарболла файлов .ml и .mli, представляющего новый протокол. Стейкхолдеры могут одобрить любое количество таких протоколов. Это процесс известен также как «одобрительное голосование», и является особенно надежной процедурой голосования.

Второй квартал

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

Третий квартал

Если кворум соблюден (включая явно воздержавшихся), и поправка получила $80\%$ голосов "за", она утверждается и заменяет протокол испытаний. В противном случае поправка отклоняется. Предполагая, что достигнут кворум $q$, минимальный кворум $Q$ обновляется как: Q0.8Q+0.2qQ←0.8Q+0.2q:

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

Четвертый квартал

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

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

Механизм Proof-of-stake

Обзор

Наш механизм proof-of-stake представляет собой сочетание нескольких идей, в том числе Slasher[@Slasher], chain-of-activity [@CoA] и proof-of-burn. Ниже приведен краткий обзор алгоритма, компоненты которого более подробно описаны ниже.

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

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

4 цикла механизма proof-of-stake:

Частота

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

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

Генерирование случайного начального числа (Random Seed)

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

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

Все показанные числа в цикле объединяются в хэш-список, а начальное число получается из корня с использованием функции получения ключа scrypt. Вывод ключа должен быть настроен таким образом, чтобы получение начального числа занимало порядка доли процента от среднего времени проверки (подтверждения) блока на типичном настольном ПК.

Процедура Follow-the-coin

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

Принцип

В мире биткоина эта идея известна как follow-the-satoshi («следуй за сатоши»). Процедура работает «как-будто», а у каждого когда-либо чеканившегося сатоши есть уникальный серийный номер. Сатоши неявно упорядочены по времени создания; случайные сатоши создаются и отслеживаются через блокчейн. Конечно, отдельные центы не отслеживаются напрямую. Вместо этого применяются правила для описания того, что происходит, когда входы объединяются и расходуются на несколько выходов.

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

Роллы коинов

Мы оптимизируем предыдущий алгоритм, создавая большие «роллы коинов», составленные из тезов (tez). Таким образом, существует около миллиона роллов. База данных отображает текущему владельцу каждый из его роллов.

В каждом адресе содержится определенный набор конкретных роллов, а также какая-то мелочь. Когда мы хотим потратить часть полного ролла, он прерывается, а его серийный номер отправляется в очередь роллов LIFO (что-то вроде «заточения» (''limbo'')). Каждая транзакция обрабатывается таким образом, чтобы свести к минимуму количество сломанных роллов. Всякий раз, когда в адресе содержится достаточно коинов для формирования ролла, из очереди извлекается серийный номер, и ролл формируется снова.

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

Небольшой недостаток этого подхода заключается в том, что ставка округляется до ближайшего целого числа роллов. Однако это обеспечивает значительное повышение эффективности по сравнению с подходом follow-the-satoshi.

Несмотря на то, что роллы пронумерованы, этот подход не исключает использования протоколов, сохраняющих функциональность, например как Zerocash. Эти протоколы могут использовать в "заточении" одну и ту же технику очередности.

Мотивация

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

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

Так, в цикле длиной $N=2048$ кто-то, владеющий долей $f$ роллов, в среднем получит $f N$ прав на майнинг, а полученная эффективная доля $f_0$ будет иметь стандартное отклонение

Если злоумышленник может выполнить поиск методом «грубой силы» по различным начальным значениям $W$, то его ожидаемое преимущество не превышает

блоков. Например, злоумышленник, контролирующий $f = 10\%$ роллов, может рассчитывать на майнинг около $205$ блоков за цикл. В секретном форке, в котором он пытается контролировать начальное число, предполагая, что вычислил более триллиона хэшей, он мог бы назначить себе около $302$ блоков, или около $14.7\%$ блоков. Обратите внимание, что:

  • Хеш, из которого получено начальное число, является дорогой функцией вывода ключа, что делает поиск методом "грубой силы" нецелесообразным.

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

Майнинг блоков

Случайное начальное число используется для многократного выбора ролла. Первый выбранный ролл позволяет стейкхолдеру майнить блок через одну минуту, второй - через две минуты - и так далее.

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

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

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

Подписывание блоков

На данный момент, у нас уже почти готова рабочая система proof of stake. Мы могли бы определить вес цепи как количество блоков, но, это откроет путь к корыстному майнингу.

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

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

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

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

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

Вес цепи

Вес - это количество подписей.

Донос

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

Донос принимает форму двух подписей. Каждая подпись чеканки или блока подписывает высоту блока, что делает доказательство неправомерных действий (злоупотребления) весьма чётким.

Хотя мы можем позволить разоблачать злодеяния кому угодно, на самом деле нет никакого смысла позволять это кому-либо еще, кроме майнера. Действительно, майнер может просто скопировать любое доказательство злоупотребления и выдать его за собственное выявление.4

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

Смарт-контракты

Тип контракта

Вместо неизрасходованных выходов Tezos использует учетные записи с отслеживанием состояния. Когда эти учетные записи указывают исполняемый код, они более широко известны как контракты. Поскольку учетная запись является типом контракта (у которого нет исполняемого кода), мы в полной общности называем оба «контрактами».

У каждого договора есть «менеджер», который в случае с аккаунтом является просто владельцем. Если договор помечен как расходуемый, менеджер может потратить средства, связанные с контрактом. Кроме того, в каждом контракте может быть указан хэш открытого ключа, который используется для подписи или майнинга блоков в протоколе proof-of-stake. Закрытый ключ может контролироваться или не контролироваться менеджером.

Формально контракт представляется в виде:

type contract = {
counter: int; (* counter to prevent repeat attacks *)
manager: id; (* hash of the contract's manager public key *)
balance: Int64.t; (* balance held *)
signer: id option; (* id of the signer *)
code: opcode list; (* contract code as a list of opcodes *)
storage: data list; (* storage of the contract *)
spendable: bool; (* may the money be spent by the manager? *)
delegatable: bool; (* may the manager change the signing key? *)
}

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

Обратите внимание, что данные представлены как тип-объединение

type data =
| STRING of string
| INT of int

где INT - 64-разрядное целое число, а строка - набор ограничительных байтов. Емкость хранилища ограничена байтами, считая целые числа как восемь байтов, а строки - как их длину.

Происхождение

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

Транзакции

Транзакция - это сообщение, отправленное из одного контракта в другой. Данное сообщение представляется в виде:

type transaction = {
amount: amount; (* amount being sent *)
parameters: data list; (* parameters passed to the script *)
(* counter (invoice id) to avoid repeat attacks *)
counter: int;
destination: contract hash;
}

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

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

Транзакция также включает в себя хеш-блок недавнего блока, который клиент считает допустимым. Если злоумышленнику удастся форсировать длительную реорганизацию с помощью форка, он не сможет включить такие транзакции, что делает форк явно фальшивым. Это последняя линия защиты. TAPOS - отличная система предотвращения длительных реорганизаций, но не достаточно подходящая для предотвращения краткосрочных двойных расходов.

Пара (account_handle, counter) почти является эквивалентом неизрасходованного вывода в Bitcoin.

Плата за хранение

Поскольку хранение данных требует больших затрат в сети, минимальная плата составляет ꜩ 1 за каждый байт увеличения объема памяти. Например, если после выполнения транзакции в хранилище было добавлено целое число, а к существующей строке в хранилище было добавлено десять символов, ꜩ 18 будет выведено из баланса контракта и уничтожено.

Код

Язык основан на стеке с высокоуровневыми типами данных, примитивами и строгой статической проверкой типов. Дизайн вдохновлен Forth, Scheme, ML и Cat. Полная спецификация набора инструкций доступна в [@language]. Она предоставляет полный набор инструкций, систему типов и семантику языка. Она служит в качестве точного руководства, а не простого введения.

Сборы (платежи)

Пока эта система похожа на процесс обработки транзакции Ethereum. Тем не менее, мы отличаемся способом оплаты. Ethereum позволяет выполнение произвольно длинных программ, требуя плату, которая линейно увеличивается со временем выполнением программы. Хотя это дает стимул для одного майнера проверить транзакцию, к сожалению, у других майнеров, которые также должны её проверить, такого стимула нет. На практике большинство интересных программ, которые можно использовать для смарт-контрактов, очень короткие. Таким образом, мы упрощаем конструкцию, устанавливая жесткое ограничение на количество шагов, которые разрешаются в программах.

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

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

Заключение

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

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

2. Напротив, инфляция майнинга Биткоина обнищает держателей биткоина в целом, а деятельность центрального банка обогащает финансовый сектор за счет вкладчиков.

3. Это стандартное ограничение на ожидание максимума W нормально распределенной переменной.

4. Доказательство zero-knowledge позволило бы любому извлекать выгоду из доносов на злодеяния, но тот факт, что это приносит выгоду, не совсем ясен.

Материалы разработаны TQ Tezos переведены на русский язык Tezos Ukraine