Привет друзья, сегодня мы собираемся изучить инструкции Aleo и SnarkVM, инструкции по установке и Hello Aleo. Мы также расширим эту тему в следующих статьях. Подпишитесь, чтобы не пропустить.
Инструкции Aleo и SnarkVM
Добро пожаловать в руководство по эксплуатации Aleo. Инструкции Aleo — это промежуточное представление программ Aleo. Все программы Leo компилируются в инструкции Aleo, которые компилируются в байт-код. Мы рекомендуем изучать и использовать инструкции Aleo, если вашей целью является детальное проектирование схем или если вы реализуете компилятор, который читает на языке высокого уровня, отличном от Leo, и хотите, чтобы ваши программы работали на Aleo.
Программы Aleo представляют собой файлы с расширением .aleo
. Программы Aleo содержат инструкции Aleo — язык программирования, подобный ассемблеру. Инструкции Aleo компилируются в коды операций AVM, которые могут выполняться виртуальной машиной Aleo.
Установите SnarkVM для компиляции и выполнения инструкций Aleo.
ИНФОРМАЦИЯ
SnarkVM в настоящее время находится в активной разработке. Пожалуйста, следите за репозиторием на GitHub на предмет возможных критических изменений.
Установка SnarkVM
Перейдите к разделу Установка для получения информации о том, как установить SnarkVM.
Привет Алео Инструкции
Разработайте свою первую программу инструкций Aleo Hello Aleo.
Алео Инструкция
Изучите основные понятия и синтаксис инструкций Aleo.
Прочтите полный список поддерживаемых кодов операций AVM.
Формальная языковая документация
Проверьте реализацию вашей программы или компилятора на соответствие грамматике инструкций Aleo.
Изучите формальную спецификацию грамматики ABNF для получения полного формального синтаксиса инструкций Aleo.
Документация по интерфейсу командной строки
Интерфейс командной строки SnarkVM предоставляет набор команд, упрощающих программирование с помощью инструкций Aleo.
Дополнительный материал
Установите Aleo по инструкции для вашего любимого редактора кода.
Монтаж
1. Установите необходимые условия
1.1 Установите Git:
1.2 Установите Rust:
1.3 Проверьте предварительные условия
git --version cargo --version
2. Создайте исходный код
Вы можете установить SnarkVM, собрав исходный код следующим образом:
# Download the source code git clone https://github.com/AleoHQ/snarkVM cd snarkvm # Build in release mode $ cargo install --path
Это создаст исполняемый файл ~/.cargo/bin/snarkvm
.
Теперь, чтобы использовать CLI SnarkVM, в вашем терминале запустите:
snarkvm
Привет Алео Инструкция
1. Создайте и постройте новый проект
Чтобы создать новый проект, мы будем использовать команду new
. Наш проект:
snarkvm new foo
Это создаст каталог foo и файлы с базовой структурой проекта:
- README.md, содержащий скелет README с инструкциями по компиляции.
- main.aleo — основной файл исходного кода.
- program.json, содержащий идентификацию проекта в формате JSON. В частности, адрес разработчика и его закрытый ключ для программы.
Файл main.aleo должен иметь следующее содержимое:
// The 'foo.aleo' program. program foo.aleo; function hello: input r0 as u32.public; input r1 as u32.private; add r0 r1 into r2; output r2 as u32.private;
Вы можете запустить программу с помощью команды snarkvm run
, за которой следует имя функции, которую вы хотите запустить, и ее входные параметры:
snarkvm run hello 2u32 3u32
Вы увидите такой вывод:
• Loaded universal setup (in 1478 ms) ⛓ Constraints • 'foo.aleo/hello' - 35 constraints (called 1 time) ➡️ Output • 5u32 ✅ Finished 'foo.aleo/hello' (in "/Users/collin/code/snarkVM/foo")
Как видите, выходные данные имеют значение 5u32
, представляющее сумму входных данных.
2. Выполнение программы
Вы можете выполнить программу с помощью команды snarkvm execute
, за которой следует имя функции, которую вы хотите выполнить, и ее входные параметры:
snarkvm execute hello 2u32 3u32
Когда выполнение завершится, вы должны увидеть следующий вывод:
• Loaded universal setup (in 1478 ms) ⛓ Constraints • 'foo.aleo/hello' - 35 constraints (called 1 time) ➡️ Output • 5u32 {"type":"execute","id":"at1 ... (transaction object truncated for brevity) ✅ Executed 'foo.aleo/hello' (in "/Users/collin/code/snarkVM/foo")
Как видите, выходные данные имеют значение 5u32
, представляющее сумму входных данных.
В вашу среду загружается универсальная установка. Подробнее об этом можно прочитать в Записке Марлина.
Как только универсальная настройка будет готова, каждая функция в вашем файле main.aleo
будет построена, и это будет создано в выходной папке:
- hello.prover — средство проверки функции
hello
. - hello.verifier — верификатор функции
hello
. - main.avm — байт-код вашей программы aleo, которую будет запускать виртуальная машина.
Как вы уже догадались, у нас есть только один файл .avm
на всю программу, но на каждую функцию есть доказывающий и верификатор.
3. Обзор программы
Давайте рассмотрим программу foo внутри файла main.aleo
:
// The 'foo.aleo' program. program foo.aleo; function hello: input r0 as u32.public; input r1 as u32.private; add r0 r1 into r2; output r2 as u32.private;
Сначала нам нужно объявить программу следующим образом:
program foo.aleo;
После этого мы можем начать писать его функции (или другие структуры Aleo, такие как структуры, записи, замыкания, как мы увидим позже).
В случае с функциями все очень просто:
function [function_name]:
Функции состоят из трех основных частей:
- Раздел ввода
Здесь мы объявляем его входные параметры:
input r0 as u32.public; input r1 as u32.private;
Все в инструкциях Aleo объявляется/хранится внутри регистра с типом (i8
,field
,bool
и т. д.) и опцией видимости (public
или private
), регистры называются r0
, r1
, ..., rn
.
В этом случае мы используем r0
и r1
для хранения входных данных, передаваемых в программу в последовательном порядке, в виде значений u32
, где мы можем хранить 32-битные целые числа без знака для выполнения нашей операции суммирования.
- Раздел инструкций
Следующий раздел содержит ядро нашей функции: здесь мы вызываем инструкции Aleo, которые нам нужны, чтобы наша программа делала то, что мы хотим. Например, выполнив операцию сложения:
add r0 r1 into r2;
За каждой инструкцией aleo следуют ее входные параметры с определенными типами, а результат сохраняется в регистре, указанном после into
.
Вы можете найти все доступные коды операций инструкций Aleo здесь.
- Раздел вывода
Подобно разделу ввода, раздел вывода делает то же самое для вывода программы. Это возврат функции.
output r2 as u32.private;
4. Типы
Aleo использует строго типизированный синтаксис. Язык поддерживает 16 примитивных типов и позволяет пользователям определять собственные типы.
Примитивные типы Aleo включают:
address boolean field group i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 scalar
Пользователи могут определять собственные типы, используя ключевые слова struct
или record
. Мы рассмотрим их в следующих нескольких разделах.
4.1 Регистры
Регистры — это места, где вы храните данные, чтобы затем иметь возможность их изменять.
4.2 Структуры
Структуры — это определяемые пользователем структуры данных. Они очень похожи на традиционные структуры обычных языков программирования. Вы можете хранить структуры в регистрах, как и любые другие типы данных Aleo.
Например, давайте создадим структуру, представляющую массив фиксированного размера из трех элементов. Добавьте это в конец файла main.aleo
:
struct array3: a0 as u32; a1 as u32; a2 as u32;
Теперь, просто в качестве примера, давайте напишем функцию, которая добавляет единицу к каждому элементу регистра с хранящимся в нем типом данных array3
.
function sum_one_to_array3: input r0 as array3.private; add r0.a0 1u32 into r1; add r0.a1 1u32 into r2; add r0.a2 1u32 into r3; cast r1 r2 r3 into r4 as array3; output r4 as array3.private;
Как видите, мы можем ввести структуру в регистр r0
и получить доступ к элементам структуры с помощью синтаксиса .
. Мы выполняем инструкцию add
для каждого элемента, сохраняя результаты в регистрах r1
, r2
и r3
и, наконец, используем команду приведения для создания новой структуры array3
в r4
.
Теперь давайте запустим его. В этом случае единственное новое, что вам нужно знать, это то, что структуры передаются в cli в следующем формате:
"{a0: 1u32, a1: 2u32, a2: 3u32}"
Теперь мы можем выполнить команду aleo run
. Очистим проект, чтобы подобрать новый код:
aleo clean && aleo run sum_one_to_array3 "{a0: 0u32, a1: 1u32, a2: 2u32}"
И на выходе мы получаем новый элемент array3
:
➡️ Output • { a0: 1u32, a1: 2u32, a2: 3u32 } ✅ Executed 'foo.aleo/sum_one_to_array3' (in "[...]/foo")
4.3 Записи
Запись — это фундаментальная структура данных для кодирования пользовательских ресурсов и состояния приложения. Записи очень похожи на структуры, но имеют два необязательных компонента:
record token: owner as address.private microcredits as u64.private
owner
относится к адресу Aleo, которому принадлежит запись, а microcredits
— это сумма кредитов, которую запись должна потратить.
Записи важны, поскольку они представляют собой базовую структуру Aleo для обработки состояния в вашем приложении.
При запуске функции Aleo в качестве входных регистров можно передавать только регистры, принадлежащие адресу приложения. В противном случае выдается ошибка и приложение не запускается.
Адрес вашего приложения для разработки можно найти в файле .env
:
{ NETWORK=testnet3 PRIVATE_KEY=APrivateKey1zkpFsQNXJwdvjKs9bRsM91KcwJW1gW4CDtF3FJbgVBAvPds }
4.4 Состояние Алео
В Aleo состояние приложения управляется посредством записей. Учетная запись Aleo может создать транзакцию для использования записи и создания новой записи на ее месте. Записи в Aleo шифруются по адресу владельца записи, что гарантирует полную конфиденциальность всех записей в Aleo.
5. Ваша первая программа Алео: Оформление перевода
Рассмотрим эту программу:
// The 'foo.aleo' program. program foo.aleo; record token: owner as address.private; microcredits as u64.private; amount as u64.private; function transfer_amount: // sender token record input r0 as token.record; // receiver address input r1 as address.private; // amount to transfer input r2 as u64.private; // final balance of sender sub r0.amount r2 into r3; // final balance of receiver add 0u64 r2 into r4; // sender token record after the transfer cast r0.owner r0.microcredits r3 into r5 as token.record; // receiver token record after the transfer cast r1 0u64 r4 into r6 as token.record; // sender new token record output r5 as token.record; // receiver new token record output r6 as token.record;
Сначала мы определяем наш собственный тип данных записи под названием token
, который имеет обязательный параметр owner
, необязательный параметр microcredits
и определяемый пользователем параметр amount
, представляющий количество имеющихся у нас токенов.
Эта функция transfer_amount
получает 3 входных параметра (запись sender
, запись receiver
и amount
) и сохраняет их в 3 регистрах (r0
, r1
и r2
). После этого он вычисляет окончательный баланс для них обоих и сохраняет его в r3
и r4
(используя инструкции sub и add для вычисления вычитания и сложения соответственно). На основе этих окончательных сумм он создает выходные записи для отправителя и получателя, сохраняя их в r5
и r6
. Наконец, обе записи отправляются из функции с помощью инструкции вывода.
Для запуска этой функции первым параметром является входная запись программы. Формат этого параметра такой же, как и для типов структур:
{ owner: aleo1x5nz5u4j50w482t5xtqc3jdwly9s8saaxlgjz0wvmuzmxv2l5q9qmypx09.private, microcredits: 0u64.private, amount: 50u64.private }
Где:
- владелец: публичный адрес программы, указанный в
PRIVATE_KEY
файла.env
. - микрокредиты: сумма кредитов, которыми владеет запись.
- остальные параметры: в зависимости от самой программы (в данном примере мы использовали параметр amount со значением 50).
Давайте запустим функцию transfer_amount
(если вы следуете инструкциям, не забудьте использовать адрес, найденный в файле program.json, в качестве поля владельца):
aleo clean && aleo run transfer_amount "{ owner: aleo1x5nz5u4j50w482t5xtqc3jdwly9s8saaxlgjz0wvmuzmxv2l5q9qmypx09.private, microcredits: 0u64.private, amount: 50u64.private }" aleo1h3gu7fky36y8r7v2x9phc434fgf20g8qd7c7u45v269jfw6vmugqjegcvp 10u64
Мы получаем следующие выходные записи:
🚀 Executing 'foo.aleo/transfer_amount'... • Calling 'foo.aleo/transfer_amount'... • Executed 'transfer_amount' (in 3520 ms) ➡️ Outputs • { owner: aleo1x5nz5u4j50w482t5xtqc3jdwly9s8saaxlgjz0wvmuzmxv2l5q9qmypx09.private, microcredits: 0u64.private, amount: 40u64.private _nonce: 2293253577170800572742339369209137467208538700597121244293392265726446806023group.public } • { owner: aleo1h3gu7fky36y8r7v2x9phc434fgf20g8qd7c7u45v269jfw6vmugqjegcvp.private, microcredits: 0u64.private, amount: 10u64.private _nonce: 2323253577170856894742339369235137467208538700597121244293392765726742543235group.public } ✅ Executed 'foo.aleo/transfer_amount' (in "[...]/foo")
Вот и все. Вы перенесли свои первые токены, определенные владельцем, в Aleo!
Примечание: в инструкциях Aleo цифра _nonce
не прописана. Компилятор выводит _nonce
в выходных данных записи. Пользователь должен предоставить его в качестве входных данных при использовании записи.
Спасибо, что дочитали эту статью до конца, и подпишитесь на уведомления.
Ниже приведены все официальные ссылки на Aleo:
Сайт — https://www.aleo.org/
Discord — https://discord.gg/aleohq
Twitter — https://twitter.com/AleoHQ
GitHub — https://github.com/AleoHQ