Эфириум и умные контракты нового поколения – конспект ВК

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

Оригинал: A Next-Generation Smart Contract and Decentralized Application Platform

Альтернативные применения blockchain технологии: цветные монеты” (“colored coins”), владение физическим объектом устройства (смарт-собственность», “smart property”), не взаимозаменяемые активы, такие как доменные имена (“Namecoin”), а также “умные контракты“, “smart contracts”) или децентрализованные автономные организации» (“decentralized autonomous organizations“) – ДАО (DAO).

Что такое Эфириум

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

Альтернативные применения блокчейна

У таких применений давняя история. Ещё в 2005 году Ник Сабо (Nick Szabo) опубликовал концепцию защищенных прав владельца собственности” “secure property titles with owner authority“, в то время оказавшуюся не готовой для практической реализации. После 2009 года, как только децентрализованный консенсус был разработан для биткойна альтернативные его применения быстро начали появляться.

Namecoin – создан в 2010 году. Децентрализованная база данных для регистрации имен.

Цветные монеты (colored coins) протокол, позволяющий людям создавать свои собственные цифровые валюты валюты специфического “цвета” и поддерживать биткойн-кошельки, работающие с валютой именно этого цвета.

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

Эфириум

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

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

Скажем. прототип Namecoin-а можно записать двумя строчками кода, валюты и репутационные системы требуют порядка двадцати строчек. Иные умные контракты и криптографические послания, которые можно прочитать при соблюдении определенных условий, также можно строить значительно проще, чем посредством исходных биткойн-скриптов – за счёт полноты и проблемной ориентации языка программирования (Solidity).

Эфириум счета (аккаунты)

В Эфириуме состояние представлено счетами, счёт представлен учетной записью с адресом длиной 20 байт, а сделки-транзакции описывают переходы из состояние в состояние, при которых переводится стоимость и информация  между счетами.

Эфириум-счет содержит четыре поля:

  • нонс-счетчик обеспечивающий однократную обработку каждой сделки
  • текущий валютный (эфирный) баланс счёта
  • контрактгый код счёта, если он присутствует
  • память счёта (по умолчанию пустая)

“Эфир” – основное внутреннее крипто-топливо Эфириума, используется для оплаты сборов за сделки-транзакции. Всего существует два типа счетов: внешние счета, контролируемые секретными ключами, и контрактные счета, контролируемые кодом их контракта.

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

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

Сообщения и операции

Термин “сделка” (“транзакция”) используется в Эфириум для обозначения подписанного пакета данных, который хранит сообщение, которое предназначено для отправки от имени внешнего счета. В сделке указывается:

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

Первые три поля обычны для любой криптовалюты.

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

Поля STARTGAS и GASPRICE играют ключевую роль в обеспечении отказоустойчивости Эфириума. Чтобы предотвратить случайные или злокозненные зацикливания или иные опасные траты вычислительных ресурсов, в каждой сделке следует ограничить допустимое количество вычислительных шагов для её выполнения. Основной единицей расчета является “эфир”; как правило, вычислительный шаг стоит 1 эфир, но некоторые операции могут стоить больше. Введена также плата в 5 эфиров за каждый байт в поле данных.

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

Сообщения

Контракты имеют возможность посылать “сообщения” другим контрактам. Сообщения – виртуальные объекты, существуют только в среде выполнения (виртуальной машине) Эфириума. В сообщении указывается:

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

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

Функция перехода в Эфириуме

ethertransition.png

  1. Проверить, что сделка правильно сформирована (правильная структура, подпись действительна, нонс правильный и правильный счет отправителя. Иначе выдать ошибку.
  2. Рассчитать оплату за транзакцию как STARTGAS * GASPRICE и определить адрес отправителя по подписи. Вычесть плату с баланса счета отправителя и увеличить нонс отправителя. Если не хватает денег, выдать ошибку.
  3. Установить переменную GAS = STARTGAS, затем уменьшить оценку в соответствии “шаговой платой” – соценкой числа шагов на каждый байт, и длиной описания сделки в байтах.
  4. Перенести оплату сделки со счета отправителя на счет получателя. Если получающий счет еще не существует, создать его. Если принимающим счета является контракт, запустить код контракта (либо до его нормального завершения, либо до исчерпания доступного эфира).
  5. Если сделка не удалась, поскольку у отправителя не хватило денег (эфира), либо превышена допустимая плата за выполнение кода, вернуть всё в исходное состояние, кроме оплаты вычислений, а также внести плату на счет майнера (оплатить услуги майнера).
  6. В противном случае, вернуть весь оставшийся эфир отправителю, и отправить комиссионные майнеру.

Например, предположим, что код контракта таков:

if !self.storage[calldataload(0)]:
    self.storage[calldataload(0)] = calldataload(32)

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

Предположим, что память контракта вначале пуста, сделка содержит 10 эфиров,  STARTGAS=2000 шагов, плата за шаг – 0,001 эфира, в ней 64 байта данных (с байтами 0-31, представляющими число 2 и байтами 32-63, представляющее строку “CHARLIE”).

Тогда для этого случая функция перехода выполняется следующим образом:

  1. Проверить, что сделка допустима и правильно сформирована.
  2. Убедиться, что у отправителя сделки имеется, по меньшей мере, 2000 * 0,001 = 2 эфира для оплаты сделки. Если это так, то вычесть 2 эфира из счета отправителя.
  3. Установить GAS = 2000; предполагая, что описание сделки занимает 170 байт и побайтовая оценка количества шагов = 5, вычесть 850, так что остаётся 1150 разрешённых шагов.
  4. Отнять 10 эфиров со счета отправителя, и добавить его в счет контракта.
  5. Выполнить код контракта. В нашем примере он проверяет, заполнена ли память контракта по индексу 2, убеждается, что там пусто (0), и поэтому устанавливает туда значение “CHARLIE”. Предположим, что это стоит 187 шагов, так что остаётся неиспользованных 1150 – 187 = 963 шагов
  6. Вернуть 963 * 0,001 = 0,963 непотраченного эфира обратно на счет отправителя, и возвратить результирующее состояние.

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

Обратите внимание, что сообщения работают таким же образом, как сделки: если выполнить сообщение невозможно из-за недостатка денег на счёте, то плата за выполнение сообщения, а также все другие платы, спровоцированные его исполнением, возвращаются, но родительские платы возвращать не нужно. Это означает, что для контракта “безопасно” вызывать подчинённый контракт, если A вызывает B с G эфиром, то A потеряет не более чем G эфиров.

Наконец, следует отметить, что существует команда CREATE, создающая контракт; результат исполнения которого определяет код вновь созданного контракта.

Выполнение кода

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

  • Стек
  • Оперативная память – бесконечно расширяемый массив байтов
  • Долговременная ассоциативная память (типа ключ/значение). В отличие от стека и оперативной памяти, сохраняется в течение длительного времени.

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

Формальная модель исполнения EVM кода на удивление проста. Состояние EVM в процессе работы полностью описывается кортежем  (block_state, сделка, сообщение, код, память, стек, указатель команды, эфир), где

block_state глобальное состояние, содержащее все счета и включает балансы и память. В начале каждого цикла исполнения из кода по указателю команды выбирается текущая исполняемая команда. Каждая команда влияет на кортеж в соответствии со своим определением. Хотя есть много способов оптимизировать выполнение EVM с помощью just-in-time компиляции, базовая реализация EVM может состоять всего из несколько сотен строк кода.

Блокчейн и майнинг

apply_block_diagram.png

Блокчейн Эфириума во многом похож на блокчейн биткойна, хотя есть и некоторые различия.
Основное различие – Эфириум-блоки содержат копию и списка сделок, и самого последнего состояния. Кроме этого, номер блока и доказательство работы также хранятся в блоке.
Основной алгоритм проверки блока в Эфириума выглядит следующим образом:
  1. Проверьте, что предыдущий блок существует и правилен
  2. Убедитесь, что временная отметка блока больше, чем у предыдущего блока, но не больше, чем на 15 минут
  3. Убедитесь, что номер блока, доказательство работы, узел сделки, соседний узел и ограничения оплаты правильны
  4. Проверьте, что правильность доказательства работы.
  5. Пусть S [0] – состояние в конце предыдущего блока.
  6. Пусть TX будет список сделок блока, всего n сделок .
    • For all i in 0…n-1, set S[i+1] = APPLY(S[i],TX[i]). Если какое-нибудь APPLY вернёт ошибку или превышен GASLIMIT, вернуть ошибку
  7. Пусть S_FINAL = S [п], тогда вознаграждение за добавление блока выплачивается майнеру
  8. Проверьте, корень дерева Merkle от S_FINAL равно конечному состоянию корня, представленному в заголовке блока. Если да, то блок признаётся правильным; иначе – недопустимым 

Такой подход может показаться крайне неэффективным, потому что нужно хранить всё с каждым блоком, но в действительности эффективность должна быть сравнима с биткойном. Причина в том, что состояние хранится в древовидной структуре, и после каждого шага меняется только небольшая часть дерева. Поэтому сами данные узлов дерева можно записать однократно, но связываться с ними двунаправленными ссылками. Для этого используется вид дерева, известный как “Patricia tree”, а также модификация концепции дерева Меркле, позволяющая эффективно вставлять, удалять и модифицировать узлы. Кроме того, поскольку вся информация о состоянии – часть последнего блока, нет необходимости отдельно хранить всю историю блокчейна – подобная стратегия, если бы была применена к Bitcoin, могла бы сэкономить 5-20% памяти.

Часто спрашивают “где” физически выполняется код контракта , Ответ прост: процесс выполнения кода контракта – часть определения функции перехода, которая, в свою очередь – часть алгоритма проверки блока, так что если сделка добавляется в блок B, выполнение кода, порожденного этой сделкой, будет распределено между всеми узлами, которые загружают и проверяют блок В, в настоящий момент или в будущем.

Приложения

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

Жетонные системы

Жетонных (маркерных) систем, базирующихся на блокчейне, известно много. От субвалют, представляющих активы типа долларов США или золота за акции компании, индивидуальных жетонов-маркеров, представляющих умную собственность, неподделываемые купоны, и даже жетонные системы без каких-либо связей с обычной стоимостью, используемые для необычной мотивации. Жетонные системы на удивление легко реализовать в Эфириуме. Важно лишь понять, что все валюты, а также жетонная система – это в принципе всего лишь база данных с одной операцией: вычесть X единиц из А и добавить X единиц В, при условии, что (1) А имел по крайней мере X единиц до сделки и (2) сделка одобрена A. Остаётся лишь реализовать эту логику в контракте.

Основной код для реализации жетонной системы на языке Serpent выглядит следующим образом:

def send(to, value):
    if self.storage[msg.sender] >= value:
        self.storage[msg.sender] = self.storage[msg.sender] - value
        self.storage[to] = self.storage[to] + value

Это, по существу буквальная реализация функции перехода в “Банковской системе” описаны ниже. Несколько дополнительных строк кода должны быть добавлены для начального распределения денежных единиц и обработки особых случаев, а также чтобы позволить другим контрактам запрашивать состояние определённых балансов. Но для этого имеется все, что нужно. Теоретически, жетонные системы на базе Эфириума могут включать в себя еще одну важную особенность – позволять платить не обязательно в фиксированной валюте, но автоматически подключать постоянно работающую валютную биржу (валютный аукцион) для пополнения баланса в требуемой валюте.

Financial derivatives and Stable-Value Currencies

Financial derivatives are the most common application of a “smart contract”, and one of the simplest to implement in code. The main challenge in implementing financial contracts is that the majority of them require reference to an external price ticker; for example, a very desirable application is a smart contract that hedges against the volatility of ether (or another cryptocurrency) with respect to the US dollar, but doing this requires the contract to know what the value of ETH/USD is. The simplest way to do this is through a “data feed” contract maintained by a specific party (eg. NASDAQ) designed so that that party has the ability to update the contract as needed, and providing an interface that allows other contracts to send a message to that contract and get back a response that provides the price.

Given that critical ingredient, the hedging contract would look as follows:

  1. Wait for party A to input 1000 ether.
  2. Wait for party B to input 1000 ether.
  3. Record the USD value of 1000 ether, calculated by querying the data feed contract, in storage, say this is $x.
  4. After 30 days, allow A or B to “reactivate” the contract in order to send $x worth of ether (calculated by querying the data feed contract again to get the new price) to A and the rest to B.

Such a contract would have significant potential in crypto-commerce. One of the main problems cited about cryptocurrency is the fact that it’s volatile; although many users and merchants may want the security and convenience of dealing with cryptographic assets, they may not wish to face that prospect of losing 23% of the value of their funds in a single day. Up until now, the most commonly proposed solution has been issuer-backed assets; the idea is that an issuer creates a sub-currency in which they have the right to issue and revoke units, and provide one unit of the currency to anyone who provides them (offline) with one unit of a specified underlying asset (eg. gold, USD). The issuer then promises to provide one unit of the underlying asset to anyone who sends back one unit of the crypto-asset. This mechanism allows any non-cryptographic asset to be “uplifted” into a cryptographic asset, provided that the issuer can be trusted.

In practice, however, issuers are not always trustworthy, and in some cases the banking infrastructure is too weak, or too hostile, for such services to exist. Financial derivatives provide an alternative. Here, instead of a single issuer providing the funds to back up an asset, a decentralized market of speculators, betting that the price of a cryptographic reference asset (eg. ETH) will go up, plays that role. Unlike issuers, speculators have no option to default on their side of the bargain because the hedging contract holds their funds in escrow. Note that this approach is not fully decentralized, because a trusted source is still needed to provide the price ticker, although arguably even still this is a massive improvement in terms of reducing infrastructure requirements (unlike being an issuer, issuing a price feed requires no licenses and can likely be categorized as free speech) and reducing the potential for fraud.

Identity and Reputation Systems

The earliest alternative cryptocurrency of all, Namecoin, attempted to use a Bitcoin-like blockchain to provide a name registration system, where users can register their names in a public database alongside other data. The major cited use case is for a DNS system, mapping domain names like “bitcoin.org” (or, in Namecoin’s case, “bitcoin.bit”) to an IP address. Other use cases include email authentication and potentially more advanced reputation systems. Here is the basic contract to provide a Namecoin-like name registration system on Ethereum:

def register(name, value):
    if !self.storage[name]:
        self.storage[name] = value

The contract is very simple; all it is is a database inside the Ethereum network that can be added to, but not modified or removed from. Anyone can register a name with some value, and that registration then sticks forever. A more sophisticated name registration contract will also have a “function clause” allowing other contracts to query it, as well as a mechanism for the “owner” (ie. the first registerer) of a name to change the data or transfer ownership. One can even add reputation and web-of-trust functionality on top.

Децентрализованное хранение файлов

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

Ключевую идею такой системы мы называем “децентрализованный Dropbox-контракт”. Работает он следующим образом. Во-первых, разбивает нужные данные на блоки, шифруя каждый блок для обеспечения приватности, и строит дерево Меркле из этих блоков. 

Затем создаётся контракт с правилом, что для каждых N блоков контракт будет выбирать случайный индекс в дереве Меркле (используя хэш предыдущего блока, доступного из кода контракта, для выработки этого случайного индекса), и передаёт X эфиров первому объекту для оплаты сделки с упрощенной проверкой-оплатой принадлежности этого блока с конкретным индексом в дереве. Когда пользователь хочет повторно загрузить файл, они могут использовать протокол микроплатежей канала (?) для восстановления файла (например, заплатить 1 Сабо за 32 килобайт). Наиболее экономный подход для плательщика – не публиковать сделку до самого конца, вместо замены сделки на более выгодную после каждых 32 kilobytes. Важной особенностью протокола является то, что, хотя может показаться, что из-за доверия многим случайным узлам возникает риск потерять файл, можно уменьшить этот риск почти до нуля путем разделения файла на множество скрытых частей, и следя за контрактами, обеспечивающими принадлежность каждой части соответствующему узлу. Если контракт все еще способен платить, это даёт криптографическое доказательство того, что файл ещё кому-то нужен (кто-то всё ещё хранит этот файл).

Просмотров: 432

Оставить комментарий


Translate »