http://libgen.rs/search.php?req=%D0%9E%D1%81%D0%B2%D0%B0%D0%B8%D0%B2%D0%B0%D0%B5%D0%BC+Ethereum
Цитата:
Антонопулос, Вуд. Осваиваем Ethereum. Создание смарт-контрактов и децентрализованных приложений
ГЛАВА 7 Cмарт-контракты и язык Solidity
Как уже говорилось в главе 2, Ethereum поддерживает два вида учетных записей: учетная запись контракта и учетная запись с внешним владельцем (ЕОА) [1]
[1] Анrл.: externally owned account (сокр. ЕОА). - Прим. ред.
Последние контролируются пользователями, часто с использованием такого ПО как кошельки, которые существуют вне платформы Ethereum. Для сравнения: учетные записи контракта контролируются программным кодом (их еще часто называют «смарт-контрактами»), который выполняется на виртуальной машине Ethereum. Если вкратце, ЕОА - это простые учетные записи, не связанные ни с кодом, ни с данными, тогда как контрактные учетные записи имеют как код, так и хранилище. ЕОА управляются транзакциями, которые создаются и криптографически подписываются приватным ключом в «реальном мире», вне и независимо от протокола; у учетных записей контракта нет приватных ключей, поэтому они «сами собой управляют» в соответствии с кодом смарт-контракта. Учетные записи обоих типов идентифицируются с помощью адреса Ethereum. В этой главе мы рассмотрим контракты и программный код, управляющий ими.
Что такое смарт-контракт?
Термин смарт-контракт (англ. smart contract) на протяжении многих лет используется для описания широкого набора разных концепций. Он придуман в 1990-х специалистом по криптографии Ником Сабо и означал «набор обещаний в цифровом виде, включая протоколы, в рамках которых стороны выполняют другие обещания» [2]
[2] А set of promises, specified in digital form, including protocols within which the parties perform оп the other promises. - Прим. Ред
С тех пор данная идея эволюционировала, особенно с появлением децентрализованных блокчейн-платформ и запуска блкочейн-сети Bitcoin в 2009 году. В контексте платформы смарт-контрактов Ethereum сам термин используется немного неправильно, так как смарт-контракты на платформе нельзя назвать ни «умными» (от англ. smart), ни юридически значимыми. Несмотря на это, данное название прижилось. В данной книге под «смарт-контрактами» понимаются неизменяемые компьютерные программы, которые детерминистически [1]
[1]То есть используется детерминистический алгоритм исполнения контракта. - Прим. ред.
выполняются на виртуальной машине (EVM) и являются частью сетевого протокола Ethereum - то есть запускаются (и живут. - Ред.) на глобальном децентрализованном компьютере Ethereum.
Давайте разберем это определение.
- Компьютерные программы. Смарт-контракты являются обычными компьютерными программами. Слово «контракт» в этом контексте не имеет юридического значения.
- Неизменяемые. После развертывания код смарт-контракта нельзя изменить. В отличие от традиционого ПО, единственной возможностью модифицировать смарт-контракт является развертывание нового экземпляра.
- Детерминизм. Результат выполнения смарт-контракта остается неизменным для всех, кто его запускает, при условии, что контекст транзакции, инициировавшей его выполнение, и состояние блокчейна Ethereum не меняются.
- Виртуальная машина (EVM). Смарт-контракты работают с очень ограниченным контекстом выполнения. Они имеют доступ к своему состоянию, содержанию транзакции, которая их вызвала, и некоторым сведениям о самых последних блоках (в сети).
- Глобальный децентрализованный компьютер. Локальный экземпляр EVM присутствует на каждой ноде сети Ethereum, но, поскольку начальное и конечное состояние, с которыми работают все ноды, являются идентичными, система в целом ведет себя как единый «глобальный компьютер».
Жизненный цикл смарт-контракта
Смарт-контракты обычно пишут на языках высокого уровня, таких как Solidity. Ноперед запуском их необходимо скомпилировать в низкоуровневый байт-код, который выполняется в EVM. После компиляции они развертываются на платформе Ethereum с помощью специальной транзакции для создания контрактов, которая отправляется по специальному адресу, Ох О ( см. «Специальные транзакции: создание контрактов» на с. 167). Каждый контракт идентифицируется с помощью адреса Ethereum, который выводится из транзакции по созданию контрактов в виде функции от исходной учетной записи и одноразового кода.
Адрес контракта можно использовать в транзакции в качестве получателя, посылая ему средства или вызывая его функции. Стоит отметить•, что, в отличие от ЕОА, у учетной записи, созданной для нового смарт-контракта, нет никаких ключей. Создатель контракта не получает никаких особых привилегий на уровне протокола (хотя вы можете вручную прописать их внутри него, в коде контракта). Вы точно не получите приватный ключ для учетной записи контракта, так как он попросту не существует. Можно сказать, что учетные записи ( смарт-)контрактов владеют сами собой.
Важно отметить, что все смарт-контракты могут быть выполнены только в результате вызова со стороны транзакции, инициированной учетной записью ЕОА. Контракты могут вызывать друга по цепочке, но первый из них всегда вызывается из ЕОА с помощью транзакции. Они никогда не работают «сами по себе» или «в фоновом режиме». Контракты, в сущности, бездействуют, пока транзакция не инициирует их выполнение - либо напрямую, либо опосредованно, внутри цепочки таких вызовов. Также стоит обратить внимание на то, что смарт-контракты никоим образом не выполняются «параллельно»; глобальный компьютер Ethereum можно считать однопоточным устройством.
Транзакции являются атомарными, независимо от того, сколько контрактов они вызывают и что эти контракты потом делают. Транзакции выполняются целиком, а все изменения, вносимые ими в глобальное состояние (контрактов, учетных записей и т. д.), записываются только в случае, если они успешно завершают свою работу. Успешное завершение означает, что программа выполнилась без каких-либо ошибок и достигла конца выполнения. Если работа нарушится из-за какой-либо ошибки, все последствия транзакции (изменения состояния) «откатываются» так, как будто она никогда не запускалась ( то есть в исходное состояние). Тем не менее факт неудачной попытки выполнить транзакцию записывается в блокчейн, а эфир, за который был куплен газ, вычитается из баланса исходной учетной записи; в остальном она не имеет никакого другого влияния на состояние контрактов или учетных записей.
Как уже упоминалось ранее, важно помнить, что код контракта невозможно изменить. Однако контракт по заданному адресу может быть «удален» вместе с его кодом и внутренним состоянием (хранилищем), в результате чего останется пустая учетная запись. Никакие транзакции, посланные по этому адресу после удаления, не приведут к выполнению кода, поскольку никакого исполняемого кода больше не существует. Чтобы удалить контракт, следует выполнить операционный код (опкод) EVM SE LFDE S TRUCT (ранее известный как SU ICI DE). Эта операция имеет «отрицательную стоимость» - то есть газ возвращается, что поощряет освобождение клиентских ресурсов, потрачен - ных на хранение состояния. Удаление контракта таким способом не стирает его историю транзакций (прошлое), поскольку сам блокчейн нельзя изменить. Также необходимо отметить, что операция SELFDE S TRUCT доступна только в случае, если автор смарт-контракта предусмотрел эту возможность в его коде. Если опкод SELFDES TRUCT отсутствует или недоступен (внутри контракта), то смарт-контракт нельзя удалить.
Введение в языки высокого уровня, доступные в Ethereum
EVM -это виртуальная машина, которая выполняет инструкции в специальном формате под названием байт-код EVM. Это похоже на то, как центральный процессор вашего компьютера выполняет машинный код, такой как х86_64. Принцип работы и языки EVM будут подробно рассмотрены в главе 13. В этом же разделе мы поговорим о том, как написать смарт-контракт таким образом, чтобы его можно было запустить в EVM.
Теоретически смарт-контракты можно писать непосредственно в виде байт-кода. но это довольно громоздкий процесс, а результат было бы очень сложно прочитать. Вместо этого большинство разработчиков для Ethereum используют при написании программ язык высокого уровня и затем преобразуют его в байт-код.
Для написания смарт-контрактов можно приспособить любой язык высокого уровня, но обеспечение совместимости с байт-кодом EVM было бы довольно обременительным занятием и в целом привело бы к определенной путанице. Смарт-контракты работают в очень ограниченной и минималистичной среде выполнения (EVM). К тому же необходимо сделать доступными некоторые системные переменные и функции, уникальные для EVM. Учитывая все это, вместо адаптации языков общего назначения для написания смарт-контрактов проще создать новый язык. В итоге появился целый ряд узкоспециализированных языков. Некоторые из них созданы для Ethereum; они поставляются вместе с компиляторами, необходимыми для генерации байт-кода, выполняемого в EVM.
В целом языки программирования можно разделить на две общие категории: декларативные и императивные, также известные как функциональные и процедурные. В декларативном программировании мы пишем функции, которые выражают логику программы, но не ее поток выполнения. Эта парадигма используется для создания программ, у которых нет побочных эффектов; это означает, что они не меняют состояние за пределами функции. К декларативным языкам программирования относятся Haskell и SQL. Для сравнения: в императивных языках (таких как С++ и Java) программист пишет набор процедур, которые объединяют в себе поток выполнения и логику программы. Некоторые языки являются «гибридными», то есть они поощряют декларативный стиль, но при этом способны реализовывать парадигмы императивного программирования. В качестве примера можно привести Lisp, JavaScript и Python. По большому счету, любой императивный язык можно использовать для написания декларативного кода, но результат часто получается не очень изящным. В то же время чисто декларативные языки нельзя применять для реализации императивной парадигмы, поскольку в них нет такого понятия, как «переменные».
Программисты чаще всего используют императивный подход, но с его помощью очень сложно писать программы, которые выполняются в точности как задумано. Тот факт, что любой участок кода может изменить состояние любого другого участка, усложняет анализ выполнения программы и создает богатую почву для ошибок. Для сравнения: декларативное программирование помогает понять поведение программы: поскольку код не имеет побочных эффектов, любой его участок можно рассматривать в отдельности от других.
Буквально каждая ошибка (bugs) в смарт-контрактах стоит денег. Поэтому при их написании очень важно исключить непреднамеренные последствия (реализации выполнения контракта). Для этого у вас должна быть возможность четко представлять ожидаемое поведении программы. Таким образом, декларативные языки программирования играют куда более важную роль в смартконтрактах, чем в ПО общего назначения. Но, как вы сами увидите, наиболее популярный язык для написания смарт-контрактов (Solidity) является императивным. Программисты, как и большинство людей, противятся переменам!
В настоящий момент для написания смарт-контрактов доступны следующие языки высокого уровня (в порядке их появления).
- LLL. Функциональный (декларативный) язык программирования с синтаксисом в стиле Lisp. Это был первый язык высокого уровня для смартконтрактов Ethereum, но в настоящеее время он используется редко.
- Serpent. Процедурный (императивный) язык программирования с синтаксисом, похожим на Python. Может также использоваться для написания функционального (декларативного) кода, хотя и с некоторыми побочными эффектами.
- Solidity. Процедурный (императивный) язык программирования с синтаксисом, похожим на JavaScript, С++ и Java. Наиболее популярное и часто используемое решение для написания смарт-контрактов в Ethereum.
- Vyper. Более молодой язык, похожий на Serpent, и тоже с синтаксисом в стиле Python. Задумывался как более чистая функциональная реализация Руthоn-подобного языка, но не как замена Serpent.
- ВатЬоо. Недавно разработанный язык, вдохновленный проектом Erlang. Поддерживает явные переходы состояния без итеративных потоков вы - полнения (циклов). Должен уменьшить количество побочных эффектов и улучшить возможность проверки. Этот язык является совсем новым, пока не имеет широкого распространения.
Как видите, в вашем распоряжении много разных языков. Однако самым популярным из них, безусловно, является Solidity, который де-факто считается стандартным языком высокого уровня не только для Ethereum, но и для других ЕVМ-подобных блокчейнов. Он будет находиться в центре нашего 1;1нимания, но мы также исследуем некоторые примеры на других высокоуровневых языках, чтобы получить представление об их разных философиях.
Написание смарт-контракта на языке Solidity
Язык Solidity создан д-ром Гэвином Вудом (одним из соавторов данной книги) специально для написания смарт-контрактов. Он непосредственно рассчитан на (их) выполнение в децентрализованном окружении глобального компьютера Ethereum. По своим характеристикам он получился довольно универсальным, поэтому его в итоге стали применять для написания смарт-контрактов на нескольких других блокчейн-платформах. В его разработке принимали участие сначала Кристиан Райтвизнер, а затем Алекс Берегшаши, Лиана Усикян, Йоичи Хираи и несколько бывших ключевых участников проекта Ethereum. На сегодня Solidity разрабатывается и поддерживается в виде независимого проекта на GitHub (github.com!ethereum/solidity).
///
- Swarm. Децентрализованная (пиринговая) сеть для хранения данных, которая вместе с WеЬЗ и Whisper используется для построения приложений DApp.
///
- WеЬЗ. Третья версия Интернета, изначально предложенная Гэвином Вудом и нацеленная на веб-приложения - как с централизованным механизмом владения и управления, так и построенных на основе децентрализованных протоколов.
- Wei. Самая мелкая деноминация эфира (ether). 1018 wei = 1 эфир.
- Whisper. Децентрализованный (пиринговый) сервис обмена сообщениями. Используется в сочетании с WеЬЗ и Swarm для построения децентрализованных приложений (DApps).
///
Гэвин Вуд был одним из первых, кто связался с Виталиком и предложил в качестве помощи свои навыки программиста на С++. Он стал соучредителем Ethereum, одним из его архитекторов и техническим директором проекта.
Вот что написал Виталик в своей статье, «Предыстория Ethereum»:
Это время, когда протокол Ethereum был всецело моим созданием. Однако с этого момента ко мне начали присоединяться новые участники. Безусловно, по части протокола самым выдающимся из них был Гэвин Вуд. Гэвин Вуд также в значительной мере отвечал за корректировку образа и видения проекта: вместо платформы для создания программируемых денег с контрактами на основе блокчейна, которые могут хранить цифровые активы и передавать их в соответствии с заранее заданными правилами, Ethereum превратился в вычислительную платформу общего пользования. Все началось с едва заметных изменений в приоритетах и терминологии, и со все большим упором на концепцию Web 3, в котором блокчейн-сеть Ethereum была лишь частью пакета децентрализованных технологий наряду с Whisper и Swarm.
Начиная с декабря 2013 года, Виталик Бутерин и Гэвин Вуд оттачивали и развивали данную идею, создавая непосредственно слой протокола, который впоследствии лег в основу блокчейн-платформы Ethereum.
///
Концепция децентрализованных приложений должна стать новой естественной вехой в развитии Всемирной паутины (World Wide Web), делая децентрализацию и пиринrовые протоколы неотъемлемой частью веб-приложений. Термин, который описывает эту эволюцию, называется wеЬЗ и означает третью «версию» web. Изначально предложенный Гэвином Вудом, он представляет новое видение и переход от сайтов с централизованным владением и управлением к приложениям, основанным на децентрализованных протоколах.
В последующих главах мы рассмотрим JаvаSсriрt-библиотеку webЗ.js, которая связывает JаvаSсriрt-приложения, запущенные в браузере, с блокчейном Ethereum. Библиотека webЗ.js также включает в себя интерфейс для пирингового сетевого хранилища под названием Swarm и пирингового сервиса обмена сообщениями Whisper. Эти три компонента, включая запускаемую в веб-браузере библиотеку JavaScript, представляют собой полноценный пакет разработки, который позволяет создавать DАрр-приложения.
///
ГЛАВА 12
Децентрализованные приложения (DApps)
В этой главе мы познакомимся с миром децентрализованных приложений (англ. decentralized applications, или сокр. DApps). То видение, которое сформировали основатели Ethereum, с самого начала было шире концепции «смартконтрактов»: ни много ни мало переосмысление Интернета и создание нового мира DАрр-приложений с метким названием web3. Смарт-контракты -это способ децентрализации управляющей логики и функций оплаты в приложениях.
Идея Web3 DАрр-приложений состоит в децентрализации остальных аспектов функциональности приложений: хранилища, механизма обмена сообщениями, системы наименований и т. д. (см рис. 12.1).
///
Децентрализованные протоколы взаимодействия на основе сообщений
Еще одним важным компонентом любого приложения является внутрипроцессная коммуникация, или взаимодействие. Это означает возможность обмениваться сообщениями между приложениями, между отдельными экземплярами приложения и между пользователями приложения. Традиционно это достигалось с помощью применения центрального сервера. Но существует множество децентрализованных решений, которые обеспечивают обмен сообщениями по пиринговой сети, - альтернатив централизованным протоколам. В контексте DАрр-приложений для Р2Р-обмена сообщениями самым упоминаемым из них является Whisper [2] , который входит в состав пакета программ и инструментов Go-Ethereum.
Заключительный аспект приложения, которое можно децентрализовать, состоит в разрешених имен (наименований). На рассмотрении сервиса имен Ethereum мы подробно остановимся позже в данной главе; а сейчас давайте рассмотрим пример DАрр-приложения.
[2] github.com/ethereum/wiki/wiki/Whisper. - Прим. авт.
///
Общая схема торгов аукциона представлена на рис. 12.2.
Основные компоненты приложения-аукциона перечислены ниже:
- смарт-контракт, реализующий выпуск невзаимозаменяемых1 токенов стандарта ERC721 (DeedReposi tory);
- смарт-контракт, реализующий аукцион (AuctionReposi tory) для продажи актов;
- клиентский веб-интерфейс на JavaScript-фpeймвopкe Vue/Vuetify;
- библиотека webЗ.js для подключения к блокчейнам экосистемы Ethereum (с помощью MetaMask или других клиентов);
- клиент Swarm для хранения ресурсов таких как изображения;
- клиент Whisper для создания чатов для каждого аукциона для участников.
Рис. 12.2. DАрр-приложение: пример простого децентрализованного аукциона
///
От «обычного» приложения к Dapp
В нескольких последних разделах мы постепенно создали децентрализованное приложение. Все началось с двух смарт-контрактов для проведения аукционов с dееd-токенами стандарта ERC721. Эти контракты спроектированы так, чтобы работать без управляющих или привилегированных учетных записей, поэтому их можно назвать по-настоящему децентрализованными. К этому мы добавили клиентскую часть на языке JavaScript, которая предоставляет удобный и дружественный пользовательский интерфейс для нашего DАрр-приложения. Оно использует децентрализованную систему хранения Swarm для размещения таких ресурсов как изображения. Также DАрр-приложение использует децентрализованный протокол взаимодействия Whisper, чтобы у каждого аукциона был отдельный зашифрованный чат без каких-либо централизованных серверов.
Мы загрузили всю клиентскую часть в Swarm, чтобы приложение не зависело ни от каких файловых или веб-серверов. Продолжая, мы зарезервировали для нашего приложения ENS имя, привязав его к клиентской части с помощью Swarm хеша; благодаря этому пользователи могут обращаться к децентрализованному аукциону по легко запоминающемуся и понятному названию.
С каждым шагом децентрализованность нашего приложения повышалась. В итоге мы получили DАрр-приложение, у которого нет центральной точки управления и отказа (в обслуживании), которое отражает идеологию wеЬЗ, Интернета нового поколения. Полная архитектура децентрализованного аукциона показана на рис. 12.14.
///
Embark GitHub: github.com/ embark-frameworkl embarkl
Документация: embark.status. im/ docsl
Репозиторий пакетов npm: www. npmjs.com/package/embark
Embark - это фреймворк, облегчающий разработку и развертывание децентрализованных приложений. Он интегрируется с Ethereum, IPFS, Whisper и Swarm, предлагая следующие возможности:
- автоматическое развертывание контрактов с доступом к ним из кода на JavaScript;
- отслеживание изменений и обновление контрактов с повторным развертыванием (если это необходимо);
- управление и взаимодействие с разными блокчейнами (например, тестовым, локальным, главным);
- управление сложными системами, состоящими из взаимозависимых контрактов;
- хранение и извлечение данных, включая файлы, хранящиеся в IPFS;
- упрощение процесса развертывания всего приложения в IPFS или Swarm.
- отправка и получение сообщений через Whisper.
Вы можете установить Embark с помощью npm:
$ npm -q install emЬark
ГЛАВА 7 Cмарт-контракты и язык Solidity
Как уже говорилось в главе 2, Ethereum поддерживает два вида учетных записей: учетная запись контракта и учетная запись с внешним владельцем (ЕОА) [1]
[1] Анrл.: externally owned account (сокр. ЕОА). - Прим. ред.
Последние контролируются пользователями, часто с использованием такого ПО как кошельки, которые существуют вне платформы Ethereum. Для сравнения: учетные записи контракта контролируются программным кодом (их еще часто называют «смарт-контрактами»), который выполняется на виртуальной машине Ethereum. Если вкратце, ЕОА - это простые учетные записи, не связанные ни с кодом, ни с данными, тогда как контрактные учетные записи имеют как код, так и хранилище. ЕОА управляются транзакциями, которые создаются и криптографически подписываются приватным ключом в «реальном мире», вне и независимо от протокола; у учетных записей контракта нет приватных ключей, поэтому они «сами собой управляют» в соответствии с кодом смарт-контракта. Учетные записи обоих типов идентифицируются с помощью адреса Ethereum. В этой главе мы рассмотрим контракты и программный код, управляющий ими.
Что такое смарт-контракт?
Термин смарт-контракт (англ. smart contract) на протяжении многих лет используется для описания широкого набора разных концепций. Он придуман в 1990-х специалистом по криптографии Ником Сабо и означал «набор обещаний в цифровом виде, включая протоколы, в рамках которых стороны выполняют другие обещания» [2]
[2] А set of promises, specified in digital form, including protocols within which the parties perform оп the other promises. - Прим. Ред
С тех пор данная идея эволюционировала, особенно с появлением децентрализованных блокчейн-платформ и запуска блкочейн-сети Bitcoin в 2009 году. В контексте платформы смарт-контрактов Ethereum сам термин используется немного неправильно, так как смарт-контракты на платформе нельзя назвать ни «умными» (от англ. smart), ни юридически значимыми. Несмотря на это, данное название прижилось. В данной книге под «смарт-контрактами» понимаются неизменяемые компьютерные программы, которые детерминистически [1]
[1]То есть используется детерминистический алгоритм исполнения контракта. - Прим. ред.
выполняются на виртуальной машине (EVM) и являются частью сетевого протокола Ethereum - то есть запускаются (и живут. - Ред.) на глобальном децентрализованном компьютере Ethereum.
Давайте разберем это определение.
- Компьютерные программы. Смарт-контракты являются обычными компьютерными программами. Слово «контракт» в этом контексте не имеет юридического значения.
- Неизменяемые. После развертывания код смарт-контракта нельзя изменить. В отличие от традиционого ПО, единственной возможностью модифицировать смарт-контракт является развертывание нового экземпляра.
- Детерминизм. Результат выполнения смарт-контракта остается неизменным для всех, кто его запускает, при условии, что контекст транзакции, инициировавшей его выполнение, и состояние блокчейна Ethereum не меняются.
- Виртуальная машина (EVM). Смарт-контракты работают с очень ограниченным контекстом выполнения. Они имеют доступ к своему состоянию, содержанию транзакции, которая их вызвала, и некоторым сведениям о самых последних блоках (в сети).
- Глобальный децентрализованный компьютер. Локальный экземпляр EVM присутствует на каждой ноде сети Ethereum, но, поскольку начальное и конечное состояние, с которыми работают все ноды, являются идентичными, система в целом ведет себя как единый «глобальный компьютер».
Жизненный цикл смарт-контракта
Смарт-контракты обычно пишут на языках высокого уровня, таких как Solidity. Ноперед запуском их необходимо скомпилировать в низкоуровневый байт-код, который выполняется в EVM. После компиляции они развертываются на платформе Ethereum с помощью специальной транзакции для создания контрактов, которая отправляется по специальному адресу, Ох О ( см. «Специальные транзакции: создание контрактов» на с. 167). Каждый контракт идентифицируется с помощью адреса Ethereum, который выводится из транзакции по созданию контрактов в виде функции от исходной учетной записи и одноразового кода.
Адрес контракта можно использовать в транзакции в качестве получателя, посылая ему средства или вызывая его функции. Стоит отметить•, что, в отличие от ЕОА, у учетной записи, созданной для нового смарт-контракта, нет никаких ключей. Создатель контракта не получает никаких особых привилегий на уровне протокола (хотя вы можете вручную прописать их внутри него, в коде контракта). Вы точно не получите приватный ключ для учетной записи контракта, так как он попросту не существует. Можно сказать, что учетные записи ( смарт-)контрактов владеют сами собой.
Важно отметить, что все смарт-контракты могут быть выполнены только в результате вызова со стороны транзакции, инициированной учетной записью ЕОА. Контракты могут вызывать друга по цепочке, но первый из них всегда вызывается из ЕОА с помощью транзакции. Они никогда не работают «сами по себе» или «в фоновом режиме». Контракты, в сущности, бездействуют, пока транзакция не инициирует их выполнение - либо напрямую, либо опосредованно, внутри цепочки таких вызовов. Также стоит обратить внимание на то, что смарт-контракты никоим образом не выполняются «параллельно»; глобальный компьютер Ethereum можно считать однопоточным устройством.
Транзакции являются атомарными, независимо от того, сколько контрактов они вызывают и что эти контракты потом делают. Транзакции выполняются целиком, а все изменения, вносимые ими в глобальное состояние (контрактов, учетных записей и т. д.), записываются только в случае, если они успешно завершают свою работу. Успешное завершение означает, что программа выполнилась без каких-либо ошибок и достигла конца выполнения. Если работа нарушится из-за какой-либо ошибки, все последствия транзакции (изменения состояния) «откатываются» так, как будто она никогда не запускалась ( то есть в исходное состояние). Тем не менее факт неудачной попытки выполнить транзакцию записывается в блокчейн, а эфир, за который был куплен газ, вычитается из баланса исходной учетной записи; в остальном она не имеет никакого другого влияния на состояние контрактов или учетных записей.
Как уже упоминалось ранее, важно помнить, что код контракта невозможно изменить. Однако контракт по заданному адресу может быть «удален» вместе с его кодом и внутренним состоянием (хранилищем), в результате чего останется пустая учетная запись. Никакие транзакции, посланные по этому адресу после удаления, не приведут к выполнению кода, поскольку никакого исполняемого кода больше не существует. Чтобы удалить контракт, следует выполнить операционный код (опкод) EVM SE LFDE S TRUCT (ранее известный как SU ICI DE). Эта операция имеет «отрицательную стоимость» - то есть газ возвращается, что поощряет освобождение клиентских ресурсов, потрачен - ных на хранение состояния. Удаление контракта таким способом не стирает его историю транзакций (прошлое), поскольку сам блокчейн нельзя изменить. Также необходимо отметить, что операция SELFDE S TRUCT доступна только в случае, если автор смарт-контракта предусмотрел эту возможность в его коде. Если опкод SELFDES TRUCT отсутствует или недоступен (внутри контракта), то смарт-контракт нельзя удалить.
Введение в языки высокого уровня, доступные в Ethereum
EVM -это виртуальная машина, которая выполняет инструкции в специальном формате под названием байт-код EVM. Это похоже на то, как центральный процессор вашего компьютера выполняет машинный код, такой как х86_64. Принцип работы и языки EVM будут подробно рассмотрены в главе 13. В этом же разделе мы поговорим о том, как написать смарт-контракт таким образом, чтобы его можно было запустить в EVM.
Теоретически смарт-контракты можно писать непосредственно в виде байт-кода. но это довольно громоздкий процесс, а результат было бы очень сложно прочитать. Вместо этого большинство разработчиков для Ethereum используют при написании программ язык высокого уровня и затем преобразуют его в байт-код.
Для написания смарт-контрактов можно приспособить любой язык высокого уровня, но обеспечение совместимости с байт-кодом EVM было бы довольно обременительным занятием и в целом привело бы к определенной путанице. Смарт-контракты работают в очень ограниченной и минималистичной среде выполнения (EVM). К тому же необходимо сделать доступными некоторые системные переменные и функции, уникальные для EVM. Учитывая все это, вместо адаптации языков общего назначения для написания смарт-контрактов проще создать новый язык. В итоге появился целый ряд узкоспециализированных языков. Некоторые из них созданы для Ethereum; они поставляются вместе с компиляторами, необходимыми для генерации байт-кода, выполняемого в EVM.
В целом языки программирования можно разделить на две общие категории: декларативные и императивные, также известные как функциональные и процедурные. В декларативном программировании мы пишем функции, которые выражают логику программы, но не ее поток выполнения. Эта парадигма используется для создания программ, у которых нет побочных эффектов; это означает, что они не меняют состояние за пределами функции. К декларативным языкам программирования относятся Haskell и SQL. Для сравнения: в императивных языках (таких как С++ и Java) программист пишет набор процедур, которые объединяют в себе поток выполнения и логику программы. Некоторые языки являются «гибридными», то есть они поощряют декларативный стиль, но при этом способны реализовывать парадигмы императивного программирования. В качестве примера можно привести Lisp, JavaScript и Python. По большому счету, любой императивный язык можно использовать для написания декларативного кода, но результат часто получается не очень изящным. В то же время чисто декларативные языки нельзя применять для реализации императивной парадигмы, поскольку в них нет такого понятия, как «переменные».
Программисты чаще всего используют императивный подход, но с его помощью очень сложно писать программы, которые выполняются в точности как задумано. Тот факт, что любой участок кода может изменить состояние любого другого участка, усложняет анализ выполнения программы и создает богатую почву для ошибок. Для сравнения: декларативное программирование помогает понять поведение программы: поскольку код не имеет побочных эффектов, любой его участок можно рассматривать в отдельности от других.
Буквально каждая ошибка (bugs) в смарт-контрактах стоит денег. Поэтому при их написании очень важно исключить непреднамеренные последствия (реализации выполнения контракта). Для этого у вас должна быть возможность четко представлять ожидаемое поведении программы. Таким образом, декларативные языки программирования играют куда более важную роль в смартконтрактах, чем в ПО общего назначения. Но, как вы сами увидите, наиболее популярный язык для написания смарт-контрактов (Solidity) является императивным. Программисты, как и большинство людей, противятся переменам!
В настоящий момент для написания смарт-контрактов доступны следующие языки высокого уровня (в порядке их появления).
- LLL. Функциональный (декларативный) язык программирования с синтаксисом в стиле Lisp. Это был первый язык высокого уровня для смартконтрактов Ethereum, но в настоящеее время он используется редко.
- Serpent. Процедурный (императивный) язык программирования с синтаксисом, похожим на Python. Может также использоваться для написания функционального (декларативного) кода, хотя и с некоторыми побочными эффектами.
- Solidity. Процедурный (императивный) язык программирования с синтаксисом, похожим на JavaScript, С++ и Java. Наиболее популярное и часто используемое решение для написания смарт-контрактов в Ethereum.
- Vyper. Более молодой язык, похожий на Serpent, и тоже с синтаксисом в стиле Python. Задумывался как более чистая функциональная реализация Руthоn-подобного языка, но не как замена Serpent.
- ВатЬоо. Недавно разработанный язык, вдохновленный проектом Erlang. Поддерживает явные переходы состояния без итеративных потоков вы - полнения (циклов). Должен уменьшить количество побочных эффектов и улучшить возможность проверки. Этот язык является совсем новым, пока не имеет широкого распространения.
Как видите, в вашем распоряжении много разных языков. Однако самым популярным из них, безусловно, является Solidity, который де-факто считается стандартным языком высокого уровня не только для Ethereum, но и для других ЕVМ-подобных блокчейнов. Он будет находиться в центре нашего 1;1нимания, но мы также исследуем некоторые примеры на других высокоуровневых языках, чтобы получить представление об их разных философиях.
Написание смарт-контракта на языке Solidity
Язык Solidity создан д-ром Гэвином Вудом (одним из соавторов данной книги) специально для написания смарт-контрактов. Он непосредственно рассчитан на (их) выполнение в децентрализованном окружении глобального компьютера Ethereum. По своим характеристикам он получился довольно универсальным, поэтому его в итоге стали применять для написания смарт-контрактов на нескольких других блокчейн-платформах. В его разработке принимали участие сначала Кристиан Райтвизнер, а затем Алекс Берегшаши, Лиана Усикян, Йоичи Хираи и несколько бывших ключевых участников проекта Ethereum. На сегодня Solidity разрабатывается и поддерживается в виде независимого проекта на GitHub (github.com!ethereum/solidity).
///
- Swarm. Децентрализованная (пиринговая) сеть для хранения данных, которая вместе с WеЬЗ и Whisper используется для построения приложений DApp.
///
- WеЬЗ. Третья версия Интернета, изначально предложенная Гэвином Вудом и нацеленная на веб-приложения - как с централизованным механизмом владения и управления, так и построенных на основе децентрализованных протоколов.
- Wei. Самая мелкая деноминация эфира (ether). 1018 wei = 1 эфир.
- Whisper. Децентрализованный (пиринговый) сервис обмена сообщениями. Используется в сочетании с WеЬЗ и Swarm для построения децентрализованных приложений (DApps).
///
Гэвин Вуд был одним из первых, кто связался с Виталиком и предложил в качестве помощи свои навыки программиста на С++. Он стал соучредителем Ethereum, одним из его архитекторов и техническим директором проекта.
Вот что написал Виталик в своей статье, «Предыстория Ethereum»:
Это время, когда протокол Ethereum был всецело моим созданием. Однако с этого момента ко мне начали присоединяться новые участники. Безусловно, по части протокола самым выдающимся из них был Гэвин Вуд. Гэвин Вуд также в значительной мере отвечал за корректировку образа и видения проекта: вместо платформы для создания программируемых денег с контрактами на основе блокчейна, которые могут хранить цифровые активы и передавать их в соответствии с заранее заданными правилами, Ethereum превратился в вычислительную платформу общего пользования. Все началось с едва заметных изменений в приоритетах и терминологии, и со все большим упором на концепцию Web 3, в котором блокчейн-сеть Ethereum была лишь частью пакета децентрализованных технологий наряду с Whisper и Swarm.
Начиная с декабря 2013 года, Виталик Бутерин и Гэвин Вуд оттачивали и развивали данную идею, создавая непосредственно слой протокола, который впоследствии лег в основу блокчейн-платформы Ethereum.
///
Концепция децентрализованных приложений должна стать новой естественной вехой в развитии Всемирной паутины (World Wide Web), делая децентрализацию и пиринrовые протоколы неотъемлемой частью веб-приложений. Термин, который описывает эту эволюцию, называется wеЬЗ и означает третью «версию» web. Изначально предложенный Гэвином Вудом, он представляет новое видение и переход от сайтов с централизованным владением и управлением к приложениям, основанным на децентрализованных протоколах.
В последующих главах мы рассмотрим JаvаSсriрt-библиотеку webЗ.js, которая связывает JаvаSсriрt-приложения, запущенные в браузере, с блокчейном Ethereum. Библиотека webЗ.js также включает в себя интерфейс для пирингового сетевого хранилища под названием Swarm и пирингового сервиса обмена сообщениями Whisper. Эти три компонента, включая запускаемую в веб-браузере библиотеку JavaScript, представляют собой полноценный пакет разработки, который позволяет создавать DАрр-приложения.
///
ГЛАВА 12
Децентрализованные приложения (DApps)
В этой главе мы познакомимся с миром децентрализованных приложений (англ. decentralized applications, или сокр. DApps). То видение, которое сформировали основатели Ethereum, с самого начала было шире концепции «смартконтрактов»: ни много ни мало переосмысление Интернета и создание нового мира DАрр-приложений с метким названием web3. Смарт-контракты -это способ децентрализации управляющей логики и функций оплаты в приложениях.
Идея Web3 DАрр-приложений состоит в децентрализации остальных аспектов функциональности приложений: хранилища, механизма обмена сообщениями, системы наименований и т. д. (см рис. 12.1).
///
Децентрализованные протоколы взаимодействия на основе сообщений
Еще одним важным компонентом любого приложения является внутрипроцессная коммуникация, или взаимодействие. Это означает возможность обмениваться сообщениями между приложениями, между отдельными экземплярами приложения и между пользователями приложения. Традиционно это достигалось с помощью применения центрального сервера. Но существует множество децентрализованных решений, которые обеспечивают обмен сообщениями по пиринговой сети, - альтернатив централизованным протоколам. В контексте DАрр-приложений для Р2Р-обмена сообщениями самым упоминаемым из них является Whisper [2] , который входит в состав пакета программ и инструментов Go-Ethereum.
Заключительный аспект приложения, которое можно децентрализовать, состоит в разрешених имен (наименований). На рассмотрении сервиса имен Ethereum мы подробно остановимся позже в данной главе; а сейчас давайте рассмотрим пример DАрр-приложения.
[2] github.com/ethereum/wiki/wiki/Whisper. - Прим. авт.
///
Общая схема торгов аукциона представлена на рис. 12.2.
Основные компоненты приложения-аукциона перечислены ниже:
- смарт-контракт, реализующий выпуск невзаимозаменяемых1 токенов стандарта ERC721 (DeedReposi tory);
- смарт-контракт, реализующий аукцион (AuctionReposi tory) для продажи актов;
- клиентский веб-интерфейс на JavaScript-фpeймвopкe Vue/Vuetify;
- библиотека webЗ.js для подключения к блокчейнам экосистемы Ethereum (с помощью MetaMask или других клиентов);
- клиент Swarm для хранения ресурсов таких как изображения;
- клиент Whisper для создания чатов для каждого аукциона для участников.
Рис. 12.2. DАрр-приложение: пример простого децентрализованного аукциона
///
От «обычного» приложения к Dapp
В нескольких последних разделах мы постепенно создали децентрализованное приложение. Все началось с двух смарт-контрактов для проведения аукционов с dееd-токенами стандарта ERC721. Эти контракты спроектированы так, чтобы работать без управляющих или привилегированных учетных записей, поэтому их можно назвать по-настоящему децентрализованными. К этому мы добавили клиентскую часть на языке JavaScript, которая предоставляет удобный и дружественный пользовательский интерфейс для нашего DАрр-приложения. Оно использует децентрализованную систему хранения Swarm для размещения таких ресурсов как изображения. Также DАрр-приложение использует децентрализованный протокол взаимодействия Whisper, чтобы у каждого аукциона был отдельный зашифрованный чат без каких-либо централизованных серверов.
Мы загрузили всю клиентскую часть в Swarm, чтобы приложение не зависело ни от каких файловых или веб-серверов. Продолжая, мы зарезервировали для нашего приложения ENS имя, привязав его к клиентской части с помощью Swarm хеша; благодаря этому пользователи могут обращаться к децентрализованному аукциону по легко запоминающемуся и понятному названию.
С каждым шагом децентрализованность нашего приложения повышалась. В итоге мы получили DАрр-приложение, у которого нет центральной точки управления и отказа (в обслуживании), которое отражает идеологию wеЬЗ, Интернета нового поколения. Полная архитектура децентрализованного аукциона показана на рис. 12.14.
///
Embark GitHub: github.com/ embark-frameworkl embarkl
Документация: embark.status. im/ docsl
Репозиторий пакетов npm: www. npmjs.com/package/embark
Embark - это фреймворк, облегчающий разработку и развертывание децентрализованных приложений. Он интегрируется с Ethereum, IPFS, Whisper и Swarm, предлагая следующие возможности:
- автоматическое развертывание контрактов с доступом к ним из кода на JavaScript;
- отслеживание изменений и обновление контрактов с повторным развертыванием (если это необходимо);
- управление и взаимодействие с разными блокчейнами (например, тестовым, локальным, главным);
- управление сложными системами, состоящими из взаимозависимых контрактов;
- хранение и извлечение данных, включая файлы, хранящиеся в IPFS;
- упрощение процесса развертывания всего приложения в IPFS или Swarm.
- отправка и получение сообщений через Whisper.
Вы можете установить Embark с помощью npm:
$ npm -q install emЬark