FlowCards: Декларативная структура для разработки dApps на Ergo
29 апреля 2020 г.

Спасибо Роберту Корнацки за доработку черновика.
Введение
ErgoScript — это язык смарт-контрактов, используемый
блокчейном Ergo. Хотя он имеет лаконичный синтаксис, заимствованный из Scala/Kotlin, он все же
может показаться запутанным на первый взгляд, потому что концептуально ErgoScript довольно отличается
от традиционных языков, которые мы все знаем и любим. Это связано с тем, что Ergo является блокчейном на основе UTXO,
в то время как смарт-контракты традиционно ассоциируются с системами на основе аккаунтов,
такими как Ethereum. Тем не менее, модель транзакций Ergo имеет много преимуществ по сравнению с моделью на основе аккаунтов,
и при правильном подходе разработка контрактов Ergo может быть значительно проще, чем написание и отладка кода Solidity.
Ниже мы рассмотрим ключевые аспекты модели контрактов Ergo, которые делают ее уникальной:
Парадигма
Модель аккаунтов Ethereum является императивной. Это означает, что типичная задача отправки монет от
Алисы к Бобу требует изменения балансов в хранилище в виде серии операций. Модель программирования на основе UTXO
в Ergo, с другой стороны, является декларативной. Контракты ErgoScript задают условия для
приема транзакции блокчейном (а не изменения состояния хранилища в результате выполнения контракта).
Масштабируемость
В модели аккаунтов Ethereum изменения в хранилище и проверки действительности выполняются
в цепочке во время выполнения кода. В отличие от этого, транзакции Ergo создаются
вне цепочки и только проверки действительности выполняются в цепочке, тем самым уменьшая количество
операций, выполняемых каждым узлом в сети. Кроме того, благодаря неизменяемости графа
транзакций возможны различные стратегии оптимизации для повышения пропускной способности
транзакций в секунду в сети. Также возможны легкие проверяющие узлы, что
дополнительно облегчает масштабируемость и доступность сети.
Общая состояние
Модель на основе аккаунтов зависит от общего изменяемого состояния, что, как известно, приводит
к сложной семантике (и тонким миллионочным ошибкам) в контексте параллельных/
распределенных вычислений. Модель Ergo основана на неизменяемом графе транзакций. Этот
подход, унаследованный от Bitcoin, хорошо сочетается с параллельной и распределенной природой
блокчейнов и облегчает работу легких бездоверительных клиентов.
Выразительная сила
Ethereum выступал за выполнение языка, полного Тьюринга, на блокчейне. Это
теоретически обещало неограниченный потенциал, однако на практике серьезные
ограничения стали очевидны из-за чрезмерного раздувания блокчейна, тонких многомиллионных ошибок, затрат на газ, которые
ограничивают сложность контракта, и других подобных проблем. Ergo, с другой стороны, расширяет UTXO, чтобы обеспечить
полноту Тьюринга, ограничивая при этом сложность самого языка ErgoScript. Та же
выразительная сила достигается другим и более семантически обоснованным способом.
С учетом всех вышеперечисленных пунктов, должно быть очевидно, что у модели Ergo много преимуществ.
В остальной части этой статьи я познакомлю вас с концепцией FlowCards - компонента для разработчиков dApp,
который позволяет проектировать сложные контракты Ergo декларативно и визуально.
От императивного к декларативному
В императивной модели программирования Ethereum транзакция представляет собой последовательность операций,
выполняемых виртуальной машиной Ethereum. Следующая функция Solidity
реализует передачу токенов от sender к receiver. Транзакция начинается, когда
sender вызывает эту функцию на экземпляре контракта и заканчивается, когда функция
возвращает результат.
// Отправляет количество существующих монет от любого вызывающего к адресу
function send(address receiver, uint amount) public {
require(amount <= balances[msg.sender], "Недостаточно средств.");
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Sent(msg.sender, receiver, amount);
}
Сначала функция проверяет предварительные условия, затем обновляет хранилище (т.е. балансы) и
в конце публикует постусловие как событие Sent. Газ, который потребляется транзакцией,
отправляется майнеру в качестве вознаграждения за выполнение этой транзакции.
В отличие от Ethereum, транзакция в Ergo представляет собой структуру данных, содержащую список входных монет,
которые она тратит, и список выходных монет, которые она создает, сохраняя общие балансы
ERGs и токенов (в чем Ergo похож на Bitcoin).
Возвращаясь к приведенному выше примеру, поскольку Ergo нативно поддерживает токены, для этого
конкретного примера отправки токенов нам не нужно писать никакого кода в ErgoScript. Вместо этого
нам нужно создать транзакцию 'send', показанную на следующем рисунке, которая описывает
ту же передачу токенов, но декларативно.

На рисунке визуально описаны следующие шаги, которые пользователь сети должен
выполнить:
- Выбрать неиспользованные боксы отправителя, содержащие в общей сложности
tB >= amountтокенов иB >= txFee + minErgERGs. - Создать выходной
targetбокс, который защищен открытым ключомreceiverсminErg
ERGs иamountтокеновT. - Создать один выход fee, защищенный контрактом
minerFeeсtxFeeERGs. - Создать один выход change, защищенный открытым ключом
sender, содержащий
B - minErg - txFeeERGs иtB - amountтокеновT. - Создать новую транзакцию, подписать ее с помощью секретного ключа отправителя и отправить в сеть Ergo.
Важно понимать, что все эти шаги выполняются вне цепочки (например, с использованием Appkit Transaction API) приложением пользователя. Узлы сети Ergo не
нуждаются в повторении этого процесса создания транзакции, им нужно только проверить уже сформированную транзакцию. Контракты ErgoScript хранятся в
входах транзакции и проверяют условия расходования. Узел выполняет
контракты в цепочке, когда транзакция проверяется. Транзакция действительна, если все
условия выполнены.
Таким образом, в Ethereum, когда мы "отправляем сумму от отправителя к получателю", мы буквально
редактируем балансы и обновляем хранилище с помощью конкретного набора команд. Это происходит
в цепочке, и, следовательно, новая транзакция также создается в цепочке в результате этого процесса.
В Ergo (как и в Bitcoin) транзакции создаются вне цепочки, и узлы сети только
проверяют их. Эффекты транзакции на состояние блокчейна заключаются в том, что входные монеты
(или боксы в терминологии Ergo) удаляются, а выходные боксы добавляются в
UTXO набор.
В приведенном выше примере мы не используем контракт ErgoScript, а вместо этого предполагаем, что проверка подписи используется в качестве предварительного условия расходования. Однако в более сложных сценариях применения нам, конечно, нужно использовать ErgoScript, что мы и собираемся обсудить далее.
От изменения состояния к проверке контекста
В примере функции send мы сначала проверили предварительное условие (require(amount <= balances[msg.sender],...)) и затем изменили состояние (т.е. обновили балансы
balances[msg.sender] -= amount). Это типично для транзакций Ethereum. Прежде чем
что-либо изменить, мы должны проверить, допустимо ли это.
В Ergo, как мы обсуждали ранее, состояние (т.е. набор UTXO боксов) изменяется неявно, когда действительная транзакция включается в блок. Таким образом, нам нужно только проверить предварительные условия перед тем, как транзакция может быть добавлена в блок. Это то, что делают контракты ErgoScript.
Невозможно "изменить состояние" в ErgoScript, потому что это язык для проверки
предварительных условий для расходования монет. ErgoScript — это чисто функциональный язык без побочных эффектов, который работает с неизменяемыми значениями данных. Это означает, что все входные, выходные и
другие параметры транзакции, доступные в скрипте, неизменяемы. Это, среди прочего,
делает ErgoScript очень простым языком, который легко изучить и безопасно использовать. Подобно
Bitcoin, каждый входной бокс содержит скрипт, который должен вернуть значение true, чтобы 1) разрешить расходование бокса (т.е. удалить из набора UTXO) и 2) добавить
транзакцию в блок.
Если быть педантичным, то, строго говоря, неправильно считать ErgoScript языком
контрактов Ergo, потому что это язык предложений (логических предикатов, формул,
и т.д.), который защищает боксы от "незаконного" расходования. В отличие от Bitcoin, в Ergo весь
контракт и часть текущего контекста блокчейна доступны каждому скрипту. Поэтому
каждый скрипт может проверять, какие выходы создаются транзакцией, их суммы ERG и токенов
(мы будем использовать эту возможность в наших примерах DEX контрактов), текущий номер блока
и т.д.
В ErgoScript вы определяете условия, при которых изменения (т.е. расходование монет) разрешены
в данном контексте. Это в контексте программирования изменений
императивно в коде контракта.
Хотя модель транзакций Ergo открывает целый ряд приложений, таких как (DEX, DeFi
приложения, LETS и т.д.), проектирование контрактов как предварительных условий для расходования
монет (или охранных скриптов) напрямую не интуитивно. В следующих разделах мы рассмотрим полезную графическую
нотацию для проектирования контрактов декларативно с использованием FlowCard диаграмм, которые являются визуальным
представлением исполняемых компонентов (FlowCards).
FlowCards направлены на радикальное упрощение разработки dApp на платформе Ergo, предоставляя
язык высокого уровня декларативного программирования, среду выполнения, формат хранения и
графическую нотацию.
Мы начнем с высокоуровневых диаграмм и перейдем к спецификации FlowCard.
Диаграммы FlowCard
Идея диаграмм FlowCard основана на следующих наблюдениях: 1) Ergo бокс
неизменяем и может быть потрачен только в транзакции, которая использует его в качестве входа. 2) Мы
поэтому можем нарисовать поток боксов через транзакции, так что боксы, входящие в
транзакцию, тратятся, а те, выходящие, создаются и добавляются в UTXO. 3) Транзакция с этой точки зрения
является просто преобразователем старых боксов в новые, сохраняя балансы ERGs и токенов.
Следующий рисунок показывает основные элементы транзакции Ergo, которые мы уже видели
ранее (теперь под названием диаграмма FlowCard).

За каждым элементом диаграммы стоит строго определенное значение (семантика),
так что диаграмма является визуальным представлением (или видом) подлежащего исполняемого
компонента (называемого FlowCard).
FlowCard может использоваться как повторно используемый компонент dApp Ergo для создания и инициации
транзакции на блокчейне Ergo. Мы обсудим это в следующих разделах.
Теперь давайте рассмотрим отдельные элементы диаграммы FlowCard по одному.
1. Имя и параметры
Каждой flow card присваивается имя и список типизированных параметров. Это похоже на
шаблон с параметрами. На приведенном выше рисунке мы можем видеть flow card Send, которая имеет пять параметров.
Параметры используются в спецификации.
2. Кошелек контракта
Это ключевой элемент flow card. Каждый бокс имеет охранный скрипт. Часто это
скрипт, который проверяет подпись по отношению к открытому ключу. Этот скрипт тривиален в ErgoScript
и определяется как шаблон def pk(pubkey: Address) = { pubkey }, где pubkey является
параметром типа Address. На рисунке шаблон скрипта применяется к
параметру pk(sender), и таким образом получается конкретный контракт кошелька. Поэтому
pk(sender) и pk(receiver) дают разные скрипты и представляют разные кошельки
на диаграмме, даже если они используют один и тот же шаблон.
Кошелек контракта содержит набор всех UTXO боксов, которые имеют данный скрипт, производный от
данного шаблона скрипта с использованием параметров flow card. Например, на рисунке
шаблон — это pk, а параметр pubkey заменяется параметром flow card sender.
3. Контракт
Хотя контракт является свойством бокса, на диаграмме мы группируем боксы по их
контрактам, поэтому кажется, что боксы принадлежат контрактам, а не наоборот. В примере у нас есть три инстанцированные контракта
pk(sender), pk(receiver) и minerFee. Обратите внимание, что pk(sender) является инстанцированием
шаблона pk с конкретным параметром sender, а minerFee является инстанцированием
предопределенного контракта, который защищает боксы вознаграждения майнера.
4. Имя бокса
На диаграмме мы можем дать каждому боксу имя. Кроме удобочитаемости диаграммы, мы также используем
имя как синоним более сложного индексированного доступа к боксу в контракте. Например,
change — это имя бокса, которое также может использоваться в условиях ErgoScript
вместо OUTPUTS(2). Мы также используем имена боксов, чтобы связать условия расходования
с боксами.
5. Боксы в кошельке
На диаграмме мы показываем боксы (темные прямоугольники) как принадлежащие кошелькам контрактов
(светлые прямоугольники). Каждый такой прямоугольник бокса соединен с серым прямоугольником транзакции
либо оранжевыми, либо зелеными стрелками, либо теми и другими. Выходной бокс (с входящей зеленой стрелкой) может включать много строк текста, где каждая
строка указывает условие, которое должно быть проверено в рамках транзакции. Первая
строка указывает условие на количество ERG, которое должно быть помещено в бокс. Другие
строки могут принимать одну из следующих форм:
amount: TOKEN- бокс должен содержать данноеamountданногоTOKENR == value- бокс должен содержать данноеvalueданного регистраRboxName ? condition- бокс с именемboxNameдолжен проверитьconditionв своем скрипте.
Мы обсудим эти условия в следующих разделах.
6. Количество ERGs в боксе
Каждый бокс должен хранить минимальное количество ERGs. Это проверяется, когда создающая транзакция
проверяется. На диаграмме количество ERGs всегда показано как первая строка (например, B: ERG или B - minErg - txFee). Указание типа значения B: ERG является необязательным и может
использоваться для удобочитаемости. Когда значение указано как формула, то эта формула должна быть
соблюдена транзакцией, которая создает бокс.
Важно понимать, что такие переменные, как amount и txFee, не являются именованными
свойствами боксов. Это параметры всей диаграммы и представляют собой некоторые
суммы. Или, другими словами, они являются общими параметрами между транзакциями (например, Заказ на продажу
и транзакции обмена из примера DEX ниже делят параметр tAmt). Таким образом,
то же самое имя связано с одним и тем же значением на протяжении всей диаграммы (в этом случае
инструменты очень помогут). Однако, когда дело доходит до в цепочке проверки этих значений,
только явные условия, которые помечены ?, преобразуются в ErgoScript. В то же время все другие условия обеспечиваются вне цепочки во время построения транзакции (например, в приложении, использующем API Appkit) и проверки транзакции, когда она добавляется в
блокчейн.
7. Количество токенов T
Бокс может хранить значения многих токенов. Токены на диаграмме имеют имена, и переменная value
может быть связана с токеном T с помощью выражения value: T. Значение value
может быть задано формулой. Если формула предваряется именем бокса, например, boxName ? formula,
то она также должна быть проверена в охранном скрипте бокса boxName. Эта
дополнительная спецификация очень удобна, потому что 1) она позволяет автоматически проверять визуальный
дизайн, и 2) условия, указанные в боксах диаграммы, достаточно для синтеза необходимых охранных скриптов. (больше об этом
ниже в разделе "От диаграмм к контрактам ErgoScript")
8. Входы Tx
Входы соединены с соответствующей транзакцией оранжевыми стрелками. Оранжевая стрелка может иметь метку одной из следующих форм:
name@index- необязательное имя с индексом, т.е.fee@0или@2. Это свойство
целевой конечной точки стрелки. Имя используется в условиях связанных боксов,
аindex— это позиция соответствующего бокса в коллекции INPUTS транзакции.!action- это свойство источника стрелки и дает имя для альтернативного
пути расходования бокса (мы увидим это в примере DEX)
Из-за альтернативных путей расходования бокс может иметь много исходящих оранжевых стрелок, в этом случае они должны быть помечены разными
действиями.
9. Транзакция
Транзакция тратит входные боксы и создает выходные боксы. Входные боксы задаются оранжевыми стрелками, и метки ожидаются для размещения входов в
правильных индексах в коллекции INPUTS. Выходные боксы задаются зелеными стрелками. Каждая транзакция должна сохранять строгий баланс значений ERG
(сумма входов == сумма выходов), и для каждого токена сумма входов >= сумма
выходов. Дизайн диаграммы требует явной спецификации значений ERG и токенов для всех выходных боксов, чтобы избежать неявных ошибок и обеспечить лучшую читаемость.
10. Выходы Tx
Выходы соединены с соответствующей транзакцией зелеными стрелками. Выходная стрелка может иметь метку следующего вида name@index, где
необязательное имя сопровождается индексом, т.е. fee@0 или @2. Это свойство
конечной точки источника стрелки. Имя используется в условиях связанных боксов, а index — это позиция соответствующего бокса в коллекции OUTPUTS транзакции.
Пример: Децентрализованная биржа (DEX)
Теперь давайте используем описанную выше нотацию для проектирования FlowCard для dApp DEX. Это достаточно просто,
но также иллюстрирует все ключевые особенности диаграмм FlowCard,
которые мы представили в предыдущем разделе.
Сценарий dApp показан на рисунке ниже:
Существует три участника (покупатель,
продавец и DEX) dApp DEX и пять различных типов транзакций, которые создаются участниками. Покупатель хочет обменять ergAmt ERGs на tAmt токенов TID (или наоборот, продавец хочет продать токены TID за ERGs, кто первым отправляет заказ, не имеет значения). И покупатель, и продавец могут отменить свои заказы в любое время. Служба сопоставления DEX вне цепочки может найти совпадающие заказы и создать транзакцию Swap, чтобы
завершить обмен.
Следующая диаграмма полностью (и формально) специфицирует все пять транзакций, которые должны
быть созданы вне цепочки dApp DEX. Она также специфицирует все условия расходования, которые
должны быть проверены в цепочке.

Давайте подробно обсудим диаграмму FlowCard и логику каждой транзакции:
Транзакция Заказа на Покупку
Покупатель создает транзакцию Buy Order. Транзакция тратит E количество ERGs
(которое мы запишем как E: ERG) из одного или нескольких боксов в кошельке pk(buyer). Транзакция создает
бокс bid с ergAmt: ERG, защищенный скриптом buyOrder. Скрипт buyOrder синтезируется из спецификации (см.
ниже в разделе "От диаграмм к контрактам ErgoScript") либо вручную, либо автоматически с помощью инструмента. Хотя нам не нужно явно определять скрипт buyOrder во время
проектирования, во время выполнения бокс bid должен содержать скрипт buyOrder как охранное предложение (которое проверяет условия расходования бокса), в противном случае условия,
указанные на диаграмме, не будут проверены.
Бокс change создается для балансировки входных и выходных сумм транзакции.
Бокс комиссии транзакции опускается, потому что его можно добавить автоматически инструментами. На практике, однако, дизайнер может явно добавить бокс комиссии в диаграмму. Это охватывает
случаи более сложных транзакций (таких как Swap), где есть много способов оплаты
комиссии за транзакцию.
Отмена Покупки, Отмена Продажи Транзакции
В любое время покупатель может отменить заказ, отправив транзакцию CancelBuy. Транзакция должна удовлетворять охранному контракту buyOrder, который защищает бокс bid.
Как видно на диаграмме, как транзакция Cancel, так и транзакция Swap могут тратить бокс bid. Когда бокс имеет альтернативы расходования (или пути расходования), каждая
альтернатива идентифицируется уникальным именем, предшествующим ! (!cancel и !swap
для бокса bid). Каждый альтернативный путь имеет специфические условия расходования. В нашем примере,
когда транзакция Cancel Buy тратит бокс bid, условие ?buyer должно быть
выполнено, что мы читаем как "подпись для адреса buyer должна быть представлена в транзакции". Таким образом, только покупатель может отменить заказ на покупку. Это условие "подписи" требуется только для альтернативного пути расходования !cancel и не требуется для !swap.
Транзакция Заказа на Продажу
Транзакция Sell Order аналогична BuyOrder в том, что она имеет дело с токенами в
дополнение к ERGs. Транзакция тратит E: ERG и T: TID токены из кошелька продавца
(указанного как контракт pk(seller)). Два выхода — это ask и change. Изменение
— это стандартный бокс для балансировки транзакции. Бокс ask хранит tAmt: TID токены для обмена
и minErg: ERG - минимальное количество ERGs, требуемое в каждом боксе.
Транзакция Swap
Это ключевая транзакция в сценарии dApp DEX. Транзакция имеет несколько условий расходования
на входных боксах, и эти условия включены в скрипты buyOrder и
sellOrder (которые проверяются, когда транзакция добавляется в
блокчейн). Однако на диаграмме эти условия не указаны в боксах bid и
ask, они вместо этого определены в выходных боксах транзакции.
Это соглашение для улучшения удобства, потому что большинство условий относятся к свойствам
выходных боксов. Мы могли бы указать эти свойства в боксе bid, но тогда нам пришлось бы
использовать более сложные выражения.
Рассмотрим выход, созданный стрелкой с меткой buyerOut@0. Эта метка говорит
нам, что выход находится на индексе 0 в коллекции OUTPUTS транзакции и
что на диаграмме мы можем ссылаться на этот бокс по имени buyerOut. Таким образом, мы можем пометить
как сам бокс, так и стрелку, чтобы дать боксу имя.
Условия, показанные в боксе buyerOut, имеют форму bid ? condition, что означает,
что они должны быть проверены в цепочке для расходования бокса bid.
Условия имеют следующий смысл:
tAmt: TIDтребует, чтобы бокс имелtAmtколичество токенаTIDR4 == bid.idтребует, чтобы регистр R4 в боксе был равен id боксаbid.script == buyerтребует, чтобы боксbuyerOutимел скрипт кошелька, где он
находится на диаграмме, т.е.pk(buyer)
Аналогичные свойства добавляются к боксу sellerOut, который указан как находящийся на индексе 1
и имя которому дается с помощью метки на самом боксе, а не на стрелке.
Транзакция Swap тратит два бокса bid и ask, используя путь расходования !swap на обоих,
однако в отличие от !cancel условия на пути не указаны. Здесь вступают в игру префиксы
bid ? и ask ?. Они используются для того, чтобы условия, перечисленные в боксе buyerOut, были перемещены в путь расходования !swap бокса bid и ask соответственно.
Если вы посмотрите на условия выходных боксов, вы увидите, что они точно специфицируют
обмен значениями между кошельками продавца и покупателя. Покупатель получает необходимое количество
токена TID, а продавец получает соответствующее количество ERGs. Транзакция Swap
создается, когда есть два совпадающих бокса с контрактами buyOrder и sellOrder.
От диаграмм к контрактам ErgoScript
Что интересно в спецификациях FlowCard, так это то, что мы можем использовать их для автоматического
генерирования необходимых ErgoTree скриптов.
С помощью соответствующей поддержки инструментов это можно сделать автоматически, но при отсутствии
таковой это можно сделать вручную. Таким образом, FlowCard позволяет нам зафиксировать и визуально
представить все проектные решения и семантические детали dApp Ergo.
Что мы собираемся сделать дальше, так это механически создать контракт buyOrder из
информации, представленной в flow card DEX.
Напомним, что каждый скрипт является предложением (логическим выражением с булевым значением), которое должно оцениваться
в true, чтобы разрешить расходование бокса. Когда у нас есть много условий, которые должны быть выполнены одновременно,
мы можем объединить их в логическую формулу, используя бинарную операцию AND, а если у нас есть
альтернативы (не обязательно исключающие), мы можем поместить их в операцию OR.
Бокс buyOrder имеет альтернативные пути расходования !cancel и !swap. Таким образом,
код ErgoScript должен иметь операцию OR с двумя аргументами - по одному для каждого пути расходования.
/** контракт buyOrder */
{
val cancelCondition = {}
val swapCondition = {}
cancelCondition || swapCondition
}
Формула для выражения cancelCondition указана в пути расходования !cancel
бокса buyOrder. Мы можем напрямую включить ее в скрипт.
/** контракт buyOrder */
{
val cancelCondition = { buyer }
val swapCondition = {}
cancelCondition || swapCondition
}
Для пути расходования !swap бокса buyOrder условия указаны в выходном боксе buyerOut
транзакции Swap. Если мы просто включим их в swapCondition, то получим синтаксически некорректный скрипт.
/** контракт buyOrder */
{
val cancelCondition = { buyer }
val swapCondition = {
tAmt: TID &&
R4 == bid.id &&
@contract
}
cancelCondition || swapCondition
}
Тем не менее, мы можем перевести условия из синтаксиса диаграммы в выражения ErgoScript,
используя следующие простые правила:
buyerOut@0==>val buyerOut = OUTPUTS(0)tAmt: TID==>tid._2 == tAmt, гдеtid = buyerOut.tokens(TID)R4 == bid.id==>R4 == SELF.id, гдеR4 = buyerOut.R4[Coll[Byte]].getscript == buyer==>buyerOut.propositionBytes == buyer.propBytes
Обратите внимание, что на диаграмме TID представляет собой идентификатор токена, но ErgoScript не имеет доступа к токенам по идентификаторам, поэтому мы не можем написать tokens.getByKey(TID). По этой причине, когда диаграмма переводится в ErgoScript, TID становится именованной константой индекса в
коллекции tokens бокса. Конкретное значение константы присваивается, когда транзакция
BuyOrder с боксом buyOrder создается. Соответствие и
согласованность между фактическим tokenId, константой TID и фактическими токенами бокса
buyerOut обеспечивается вне цепочки кодом приложения, что совершенно
возможно, поскольку все транзакции создаются приложением с использованием FlowCard в качестве
руководящей спецификации. Это может показаться слишком сложным, но это часть перевода
от спецификации диаграммы к фактическому исполняемому коду приложения, большая часть которого может быть
автоматизирована.
После преобразования мы можем получить корректный скрипт, который проверяет все необходимые
предварительные условия для расходования бокса buyOrder.
/** контракт buyOrder */
def DEX(buyer: Addrss, seller: Address, TID: Int, ergAmt: Long, tAmt: Long)
{
val cancelCondition: SigmaProp = { buyer } // проверка подписи покупателя (ProveDlog)
val swapCondition = OUTPUTS.size > 0 && { // обеспечение доступа к OUTPUTS
val buyerOut = OUTPUTS(0) // из buyerOut@0
buyerOut.tokens.size > TID && { // обеспечение доступа к токенам
val tid = buyerOut.tokens(TID)
val regR4 = buyerOut.R4[Coll[Byte]]
regR4.isDefined && { // обеспечение доступа к R4
val R4 = regR4.get
tid._2 == tAmt && // из tAmt: TID
R4 == SELF.id && // из R4 == bid.id
buyerOut.propositionBytes == buyer.propBytes // из script == buyer
}
}
}
cancelCondition || swapCondition
}
Аналогичный скрипт для бокса sellOrder можно получить, используя те же правила перевода.
С помощью инструментов код контрактов может быть механически сгенерирован из
спецификации диаграммы.
Заключение
Декларативные модели программирования уже выиграли битву против императивного программирования
в многих областях применения, таких как Большие Данные, Обработка потоков, Глубокое обучение, Базы данных,
и т.д. Ergo является пионером декларативной модели разработки dApp как лучшей и более безопасной
альтернативы ныне популярной императивной модели смарт-контрактов.
Концепция FlowCard смещает акцент с написания контрактов ErgoScript на
общий поток значений (отсюда и название), так что ErgoScript всегда
может быть сгенерирован из них. Вам никогда не придется смотреть на код ErgoScript, как только инструменты
будут на месте.
Вот возможные следующие шаги для будущей работы:
-
Формат хранения для спецификации FlowCard и соответствующий стандартизированный формат файла EIP
(Json/XML/Protobuf). Это позволит различным инструментам (Редактор диаграмм, Среда выполнения, dApps и т.д.)
создавать и использовать файлы*.flowcard. -
Просмотрщик FlowCard, который может генерировать диаграммы из файлов
*.flowcard. -
Среда выполнения FlowCard, которая может запускать файлы
*.flowcard, создавать и отправлять транзакции в сеть Ergo. -
Инструмент проектирования FlowCard, который может упростить разработку сложных диаграмм. Это сделает проектирование и проверку контрактов Ergo приятным опытом, больше похожим на рисование,
чем на кодирование. Кроме того, правильность всего сценария dApp может быть
проверена и контролируема инструментами.
Ссылки
Share post
13 августа 2025 г.
9 июля 2025 г.
12 мая 2025 г.






