Контракты на блокчейн с сохранением состояния и без сохранения состояния

Или что не так с контрактами Ethereum и как новые облегченные контракты Ardor могут это исправить

См. Другие статьи о легких контрактах

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

Это своего рода пример, с которого каждый новый разработчик смарт-контрактов будет начинать с ethereum.org.

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

Контракты Ethereum отслеживают состояние

Массив balanceOf в строке №8 - мать всего зла (с точки зрения информатики). Этот массив поддерживает балансы учетных записей, содержащих MyToken, на программном жаргоне мы называем этот массив balanceOf «состоянием» контракта, поскольку эта информация сохраняется между вызовами контракта и хранится в блокчейне.

Что плохого в этом подходе, так это то, что он является магнитом для проблем параллелизма и различных экзотических векторов атак.

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

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

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

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

Наличие общего состояния вызывает другие проблемы, например, что, если между строками № 26 и № 27 разработчик контракта решит вызвать внешний контракт? Этот внешний контракт может вызвать исключение, в результате которого отправитель останется без баланса, даже если этот баланс еще не был зачислен получателю.

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

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

На помощь приходят облегченные контракты Ardor

Ardor, основанный на технологии NXT, уже имеет несколько способов безопасного сохранения состояния в блокчейне, используя такие объекты, как сообщения, свойства учетной записи, псевдонимы, облачные данные, различные типы токенов и многое другое. Все эти объекты встроены в основную цепочку блоков с использованием собственных типов транзакций и API.

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

Прямой пример 1: 1 облегченного контракта, подобного вышеуказанному контракту Ethereum, невозможен, поскольку в Ardor все, что вам нужно для изменения баланса токенов, - это вызвать API-интерфейс transferAsset, поэтому давайте рассмотрим другой пример, чтобы увидеть, как это работает.

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

Https://bitbucket.org/Jelurida/ardor/src/master/addons/src/java/com/jelurida/ardor/contracts/HelloWorld.java

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

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

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

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