Перейти к основному содержимому

Создание и развертывание смарт-контрактов с помощью Solidity

· 8 мин. чтения

1. Обзор

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

Прежде чем мы объясним, что такое смарт-контракт, давайте начнем с определения блокчейна :

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

Давайте посмотрим, как мы можем создавать смарт-контракты на Ethereum с надежностью:

2. Эфириум

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

Децентрализованное приложение ( Dapp ) — это инструмент, с помощью которого люди и организации, находящиеся на разных сторонах взаимодействия, могут собираться вместе без какого-либо централизованного посредника. Ранние примеры Dapps включают BitTorrent (обмен файлами) и биткойн (валюта).

Мы можем описать Ethereum как блокчейн со встроенным языком программирования.

2.1. Виртуальная машина Ethereum (EVM)

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

Первый тип учетной записи, вероятно, наиболее знаком обычному пользователю, использующему сеть. Его имя — EOA (внешняя учетная запись); он используется для передачи значения (например, эфира ) и управляется закрытым ключом.

С другой стороны, есть еще один тип счета, который является контрактом. Давайте продолжим и посмотрим, о чем идет речь:

3. Что такое смарт-контракт?

Смарт-контракт — это автономный скрипт, обычно написанный на Solidity, скомпилированный в двоичный файл или JSON и развернутый по определенному адресу в блокчейне . Точно так же, как мы можем вызвать конкретную конечную точку URL-адреса RESTful API для выполнения некоторой логики через HttpRequest , мы можем аналогичным образом выполнить развернутый смарт-контракт по определенному адресу , отправив правильные данные вместе с необходимым Ethereum для вызова развернутого и скомпилированная функция Solidity .

С точки зрения бизнеса это означает, что функции смарт-контрактов могут быть изначально монетизированы (аналогично функции AWS Lambda, которая позволяет пользователям платить за вычислительный цикл , а не за экземпляр ). Важно отметить, что запуск функций смарт-контракта не требует затрат на Ethereum.

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

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

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

3.1. Солидность

Основным языком, используемым в Ethereum, является Solidity — язык, похожий на Javascript, разработанный специально для написания смарт-контрактов. Solidity имеет статическую типизацию, поддерживает наследование, библиотеки и сложные определяемые пользователем типы среди других функций.

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

4. Создание смарт-контракта с Solidity

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

pragma solidity ^0.4.0;

В нашем примере имя контракта — Greeting , и, как мы видим, его создание похоже на создание класса в Java или другом объектно-ориентированном языке программирования:

contract Greeting {
address creator;
string message;

// functions that interact with state variables
}

В этом примере мы объявили две переменные состояния: Creator и message . В Solidity мы используем тип данных с именем address для хранения адресов учетных записей.

Далее нам нужно инициализировать обе переменные в конструкторе.

4.1. Конструктор

Мы объявляем конструктор, используя ключевое слово function , за которым следует имя контракта (точно так же, как в Java).

Конструктор — это специальная функция, которая вызывается только один раз при первом развертывании контракта в блокчейне Ethereum. Мы можем объявить только один конструктор для контракта:

function Greeting(string _message) {
message = _message;
creator = msg.sender;
}

Мы также вводим исходную строку _message в качестве параметра в конструктор и устанавливаем ее в переменную состояния сообщения .

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

Потенциально мы могли бы использовать эту информацию для реализации контроля доступа к определенным функциям.

4.2. Методы установки и получения

Наконец, мы реализуем методы установки и получения сообщения:

function greet() constant returns (string) {
return message;
}

function setGreeting(string _message) {
message = _message;
}

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

Теперь мы можем изменить значение состояния в контракте, вызвав функцию setGreeting . Любой может изменить значение, просто вызвав эту функцию. Этот метод не имеет возвращаемого типа, но принимает в качестве параметра тип String .

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

5. Взаимодействие со смарт-контрактом

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

Есть два способа сделать это:

Infura — самый простой вариант, поэтому мы запросим токен бесплатного доступа . После регистрации нам нужно выбрать URL-адрес тестовой сети Rinkeby: «https://rinkeby.infura.io/<токен>».

Чтобы иметь возможность совершать транзакции со смарт-контрактом из Java, нам нужно использовать библиотеку под названием Web3j . Вот зависимость Maven:

<dependency>
<groupId>org.web3j</groupId>
<artifactId>core</artifactId>
<version>3.3.1</version>
</dependency>

И в Градле:

compile ('org.web3j:core:3.3.1')

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

5.1. Создание кошелька

Web3j позволяет нам использовать некоторые его функции из командной строки:

  • Создание кошелька
  • Управление паролями кошелька
  • Перевод средств с одного кошелька на другой
  • Создание оболочек функций смарт-контракта Solidity

Инструменты командной строки можно получить в виде zip-файла/tarball со страницы релизов репозитория проекта в разделе загрузок или для пользователей OS X через homebrew:

brew tap web3j/web3j
brew install web3j

Чтобы сгенерировать новый кошелек Ethereum, мы просто вводим в командной строке следующее:

$ web3j wallet create

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

Мы будем использовать его на следующем шаге для запроса эфира.

5.2. Запрос эфира в тестовой сети Ринкеби

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

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

5.3. Создание оболочки смарт-контракта

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

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

$ solc Greeting.sol --bin --abi --optimize -o <output_dir>/

Последний создаст два файла: Greeting.bin и Greeting.abi. Теперь мы можем сгенерировать код оболочки с помощью инструментов командной строки web3j:

$ web3j solidity generate /path/to/Greeting.bin 
/path/to/Greeting.abi -o /path/to/src/main/java -p com.your.organisation.name

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

6. Взаимодействие со смарт-контрактом

В нашем основном классе мы начинаем с создания нового экземпляра web3j для подключения к удаленным узлам в сети:

Web3j web3j = Web3j.build(
new HttpService("https://rinkeby.infura.io/<your_token>"));

Затем нам нужно загрузить файл нашего кошелька Ethereum:

Credentials credentials = WalletUtils.loadCredentials(
"<password>",
"/path/to/<walletfile>");

Теперь давайте развернем наш смарт-контракт:

Greeting contract = Greeting.deploy(
web3j, credentials,
ManagedTransaction.GAS_PRICE, Contract.GAS_LIMIT,
"Hello blockchain world!").send();

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

String contractAddress = contract.getContractAddress();

Все транзакции, совершенные с контрактом, можно увидеть в URL-адресе: « https://rinkeby.etherscan.io/address/<contract_address>».

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

TransactionReceipt transactionReceipt = contract.setGreeting("Hello again").send();

Наконец, если мы хотим просмотреть новое сохраненное значение, мы можем просто написать:

String newValue = contract.greet().send();

7. Заключение

В этом руководстве мы увидели, что Solidity — это язык программирования со статической типизацией, предназначенный для разработки смарт-контрактов, работающих на EVM.

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

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

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

Как всегда, образцы кода можно найти на GitHub .