DEV Community

EgorMajj
EgorMajj

Posted on

Инструкция по началу работы с Aleo

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

Прежде чем мы начнем, убедитесь, что у вас установлен и запущен Rust. Вы можете найти несколько примеров в репозитории проекта Aleo

Установите Aleo

  • Сборка из исходного кода

Вы можете установить aleo, собрав его из исходного кода следующим образом (мы рекомендуем устанавливать Aleo именно таким образом):

# Download the source code
git clone https://github.com/AleoHQ/aleo && cd aleo

# Install Aleo
$ cargo install --path .
Enter fullscreen mode Exit fullscreen mode

Сборка из crates.io

(Эта опция устарела, мы рекомендуем собирать из исходников, чтобы использовать последнюю версию)

Также вы можете установить сборник aleo из репозитория crates.io. В терминале запустите:

cargo install aleo
Enter fullscreen mode Exit fullscreen mode

На этом этапе вы можете запустить команду aleo в терминале:

aleo
Enter fullscreen mode Exit fullscreen mode

Первые шаги

Создание нового проекта Aleo

Чтобы создать новый проект, мы воспользуемся командой new. Наш проект:

aleo new foo
Enter fullscreen mode Exit fullscreen mode

Это создаст папку foo и файлы с базовой структурой проекта:

  • README.md скелет README с инструкциями по сборке
  • main.aleo основной файл исходного кода.
  • program.json, содержащий идентификационные данные проекта в формате JSON. В частности, адрес разработчика и его закрытый ключ для программы.

Давайте откроем main.aleo и зададим функцию sum:

// The 'foo.aleo' program.
program foo.aleo;

function sum:
    input r0 as u32.public;
    input r1 as u32.private;
    add r0 r1 into r2;
    output r2 as u32.private;
Enter fullscreen mode Exit fullscreen mode

О том, что означает этот код, мы поговорим позже. Сначала мы построим нашу программу foo.

Сборка проекта Aleo

Чтобы собрать проект, запустите его в главной папке:

aleo build
Enter fullscreen mode Exit fullscreen mode

В результате вы увидите следующее:

 Compiling 'foo.aleo'...

  Loaded universal setup (in 1478 ms)
  Built 'sum' (in 6323 ms)

 Built 'foo.aleo' (in "[...]/foo")
Enter fullscreen mode Exit fullscreen mode

Сначала в вашу систему загружается "universal setup". Подробнее об этом можно прочитать здесь или в документе Marlin.

Как только universal setup будет готова, каждая функция в вашем файле main.aleo собирается, создавая это в папке output:

  • sum.prover проверяющая для функции sum.
  • sum.verifier верификатор для функции sum.
  • main.avm байткод вашей программы aleo для запуска виртуальной машиной.

Как вы уже догадались, у нас всего один .avm-файл для всей программы, но для каждой функции есть свой проверяющий и верификатор.

Запуск программы

Вы можете запустить программу с помощью команды aleo run, за которой следует имя функции, которую вы хотите выполнить, и ее входные параметры. Давайте запустим наши функции sum:

aleo run sum 2u32 3u32
Enter fullscreen mode Exit fullscreen mode

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

🚀 Executing 'foo.aleo/sum'...

  Calling 'foo.aleo/sum'...
  Executed 'sum' (in 1170 ms)

➡️  Output

  5u32

 Executed 'foo.aleo/sum' (in "[...]/foo")
Enter fullscreen mode Exit fullscreen mode

Как вы можете видеть здесь, выполнение функции sum длилось 1170 мс, а выходному регистру было присвоено значение 5u32, представляющее sum входов.

Обзор программы

Давайте рассмотрим программу foo внутри файла main.aleo:

// The 'foo.aleo' program.
program foo.aleo;

function sum:
    input r0 as u32.public;
    input r1 as u32.private;
    add r0 r1 into r2;
    output r2 as u32.private;
Enter fullscreen mode Exit fullscreen mode

Во-первых, нам нужно заявить программу следующим образом:

program foo.aleo;
Enter fullscreen mode Exit fullscreen mode

Затем мы можем начать писать её функции (или другие структуры Aleo, такие как интерфейсы, записи, закрытия, как мы увидим позже). В случае с функциями все очень просто:

function [function_name]:
Enter fullscreen mode Exit fullscreen mode

Функции состоят из трех основных частей:

  • Раздел input "ввода". Здесь мы определяем его входные параметры:
    input r0 as u32.public;
    input r1 as u32.private;
Enter fullscreen mode Exit fullscreen mode

Все в инструкциях Aleo заявляются/хранятся внутри регистра с типом (i8,field,bool, и т.д.) и параметром видимости (public или private). Регистры имеют имена r0, r1, ..., rn. Более подробно о регистрах, типах и видимости мы поговорим позже.

Итак, в данном случае мы используем r0 и r1 для хранения входов, передаваемых в последовательном порядке в программу, в виде значений u32, где мы можем хранить 32-битные беззнаковые целые числа для выполнения нашей функции sum.

  • Раздел instructions "инструкций". Следующий раздел, заключающий в себе ядро нашей функции. Здесь мы указываем количество инструкций Aleo, необходимых для того, чтобы наша программа сделала то, что мы хотим. Например, выполнение функции add:
    add r0 r1 into r2;
Enter fullscreen mode Exit fullscreen mode

За каждой инструкцией Aleo следуют ее входные параметры с заданными типами, а результат сохраняется в регистре into. Вы можете найти все доступные инструкции Aleo здесь.

  • Раздел output "вывода". Подобно разделу ввода, раздел вывода делает то же самое для вывода программы. Это возвращаемое значение функции.
 output r2 as u32.private;
Enter fullscreen mode Exit fullscreen mode

Разбираемся в некоторых концепциях

Типы

Aleo является типизированным языком. В настоящее время доступны следующие типы данных:

Boolean
Field
Group
I8
I16
I32
I64
I128
U8
U16
U32
U64
U128
Scalar
Enter fullscreen mode Exit fullscreen mode

Определены пользователем:

Interface
Record
Enter fullscreen mode Exit fullscreen mode

Registers "Регистры"

Регистр - это место, где вы храните данные, чтобы затем иметь возможность их изменять.

Interfaces "Интерфейсы"

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

Например, давайте создадим интерфейс, представляющий массив фиксированного размера из 3 элементов. Добавьте это в нижнюю часть файла main.aleo:

interface array3:
    a0 as u32;
    a1 as u32;
    a2 as u32;
Enter fullscreen mode Exit fullscreen mode

Теперь, для примера, давайте закодируем функцию, которая добавляет единицу к каждому элементу регистра с хранящимся в нем типом данных 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;
Enter fullscreen mode Exit fullscreen mode

Как видите, мы можем ввести интерфейс в регистр r0 и получить доступ к элементам интерфейса с помощью синтаксиса . Мы выполняем инструкцию add над каждым элементом, сохраняя результаты в регистрах r1, r2 и r3, и, наконец, используем команду cast для создания нового интерфейса array3 в r4.

Теперь давайте запустим его. В этом случае единственное, что вам нужно знать, это то, что интерфейсы передаются в cli в следующем формате:

"{a0: 1u32, a1: 2u32, a2: 3u32}"
Enter fullscreen mode Exit fullscreen mode

Теперь мы можем выполнить команду aleo run. Мы очистим проект, чтобы подхватить новый код:

aleo clean && aleo run sum_one_to_array3 "{a0: 0u32, a1: 1u32, a2: 2u32}"
Enter fullscreen mode Exit fullscreen mode

И на выходе мы получаем новый элемент набора array3:

🚀 Executing 'foo.aleo/sum_one_to_array3'...

  Calling 'foo.aleo/sum_one_to_array3'...
  Executed 'sum_one_to_array3' (in 1331 ms)

➡️  Output

  {
  a0: 1u32,
  a1: 2u32,
  a2: 3u32
}

 Executed 'foo.aleo/sum_one_to_array3' (in "[...]/foo")
Enter fullscreen mode Exit fullscreen mode

Records "Записи"

Record - это фундаментальная структура данных для кодирования пользовательских активов и состояния приложения. Они очень похожи на интерфейсы, но у них есть два необязательных параметра:

record token:
    owner as address.private
    gates as u64.private
Enter fullscreen mode Exit fullscreen mode

owner означает адрес Aleo, которому принадлежит запись, а gates - количество кредитов, которые запись должна потратить.

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

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

Адрес приложения для разработки можно найти в файле program.json:

{
    "program": "foo.aleo",
    "version": "0.0.0",
    "description": "",
    "development": {
        "private_key": "APrivateKey1zkpFsQNXJwdvjKs9bRsM91KcwJW1gW4CDtF3FJbgVBAvPds",
        "address": "aleo1x5nz5u4j50w482t5xtqc3jdwly9s8saaxlgjz0wvmuzmxv2l5q9qmypx09"
    },
    "license": "MIT"
}
Enter fullscreen mode Exit fullscreen mode

Состояние Aleo в двух словах

В Aleo состояние приложения управляется с помощью записей. Учетная запись Aleo может создать транзакцию для потребления записи и создания новой записи на ее месте. Записи в Aleo шифруются по адресу владельца записи, что обеспечивает полную конфиденциальность всех записей в Aleo.

Ваша первая программа Aleo: Выполнение перевода

Рассмотрим эту программу:

// The 'foo.aleo' program.
program foo.aleo;

record token:
    owner as address.private;
    gates 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.gates 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;
Enter fullscreen mode Exit fullscreen mode

Во-первых, мы определили наш собственный тип данных записи под названием token, который имеет два необязательных параметра, owner и gates, и определяемый пользователем параметр под названием amount, представляющий количество имеющихся у нас токенов.

Функция transfer_amount получает 3 входных параметра (запись sender, запись receiver и amount) и сохраняет их в 3 регистрах (r0, r1 и r2). После этого она вычисляет окончательный баланс для обоих регистров и сохраняет его в r3 и r4 (используя инструкции sub и add для вычисления вычитания и сложения). С этими итоговыми суммами он создает выходные записи для отправителя и получателя, сохраняя их в r5 и r6. Наконец, обе записи отправляются из функции с помощью инструкции output.

Для запуска этой функции первым параметром является входная запись программы. Формат этого параметра такой же, как и для интерфейсных типов:

{
  owner: aleo1x5nz5u4j50w482t5xtqc3jdwly9s8saaxlgjz0wvmuzmxv2l5q9qmypx09.private,
  gates: 0u64.private,
  amount: 50u64.private
}
Enter fullscreen mode Exit fullscreen mode

где:

  • owner: публичный адрес программы, как указано в development.address файла build/program.json.
  • gates: параметры, которые есть у записи.
  • другие параметры: зависят от самой программы (в данном примере мы использовали параметр amount со значением 50).

Запустим функцию transfer_amount (если вы следуете за нами, не забудьте использовать адрес, найденный в program.json для поля owner):

aleo clean && aleo run transfer_amount "{
owner: aleo1x5nz5u4j50w482t5xtqc3jdwly9s8saaxlgjz0wvmuzmxv2l5q9qmypx09.private,
gates: 0u64.private,
amount: 50u64.private
}" aleo1h3gu7fky36y8r7v2x9phc434fgf20g8qd7c7u45v269jfw6vmugqjegcvp 10u64
Enter fullscreen mode Exit fullscreen mode

Мы получаем следующие результаты:

🚀 Executing 'foo.aleo/transfer_amount'...

  Calling 'foo.aleo/transfer_amount'...
  Executed 'transfer_amount' (in 3520 ms)

➡️  Outputs

  {
  owner: aleo1x5nz5u4j50w482t5xtqc3jdwly9s8saaxlgjz0wvmuzmxv2l5q9qmypx09.private,
  gates: 0u64.private,
  amount: 40u64.private
  _nonce: 2293253577170800572742339369209137467208538700597121244293392265726446806023group.public
}
  {
  owner: aleo1h3gu7fky36y8r7v2x9phc434fgf20g8qd7c7u45v269jfw6vmugqjegcvp.private,
  gates: 0u64.private,
  amount: 10u64.private
  _nonce: 2323253577170856894742339369235137467208538700597121244293392765726742543235group.public
}

 Executed 'foo.aleo/transfer_amount' (in "[...]/foo")
Enter fullscreen mode Exit fullscreen mode

Вот и все. Вы передали свои первые собственные определенные токены в Aleo!

Примечание: _nonce не записывается в инструкции Aleo. Сборка выводит _nonce в выводах записей. Пользователь должен указать его в качестве ввода при использовании записи.

Итоговые замечания

Программы Aleo могут создавать и исполнять криптографические схемы, написанные в инструкциях Aleo. Это вводит некоторые ограничения, которых нет в обычных языках программирования. Например, при использовании тернарного оператора для наличия ответвления в потоке программы необходимо заранее иметь оба результата (т.е. результат каждого ответвления должен быть вычислен и известен до выполнения тернарного оператора). Логическое сравнение должно быть между регистрами, а не между возвратными значениями вызываемых функций.

Источник - https://www.entropy1729.com/getting-started-aleo-instructions/

Перевел - egormajj#0340

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

Top comments (0)

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

👋 Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay