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

Это дало нам, Fueled, задачу и возможность просто разобраться в этом, покопавшись в фактическом исходном коде EOS. Мы изложили то, что узнали, читая, так что вам не нужно (надеюсь). Я лично не гарантирую, что все в этой статье полностью правильно или все еще актуально, поскольку разработка EOS продолжается, но это может дать вам лучшее представление о базе данных EOS и ее функциях.

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

Введение в базу данных EOS

База данных EOS - это специальная функция, которая позволяет хранить индексированные данные в цепочке блоков, отформатированные внутри определенных структур данных. Наличие базы данных в блокчейне не означает, что каждый имеет право выполнять запись / чтение в этой базе данных. База данных EOS в основном состоит из нескольких уровней, как описано в contracts/eosiolib/db.h, имеет простую идею:

 * EOS.IO organizes data according to the following broad structure:
 *
 * — **code** — the account name which has write permission
 *    — **scope** — an account where the data is stored
 *       — **table** — a name for the table that is being stored
 *          — **record** — a row in the table

Есть некоторые используемые термины, которые отличаются от тех, что вы слышали раньше, здесь я изложил, что означают эти термины.
- code - это число, которое соответствует коду вашего контракта. Вы, возможно, видели это раньше, создавая смарт-контракты на EOS, это «идентификатор» смарт-контракта.
- scope Поскольку контракт может быть развернут несколько раз, идентификатор контракта равен не хватит. Область видимости может быть любой, но обычно это идентификатор учетной записи, с которой она развертывается.
- table Имя таблицы.
- record Надеюсь, это говорит само за себя.

Структурирование ваших таблиц

Таблицы базы данных EOS могут быть отформатированы по struct типу данных, в этих структурах вы можете определить именование и определение типа ваших свойств этой таблицы.

Давайте посмотрим на пример:

Итак, давайте пройдемся по частям кода и выделим некоторые из требований, определенных EOS.

Аннотации ABI

// @abi table proposal i64

Для развертывания контракта вы запустите код с помощью команды eosiocpp, компилятор смарт-контрактов EOS может считывать комментарии над вашими struct и общедоступными функциями. есть 2 типа, которые вы можете пройти; action и table, что говорит само за себя. Эта аннотация комментария извлекается генератором abi (находится в библиотеках / abi_generator / abi_generator.cpp # 201) для добавления этого метода или определения таблицы в вывод ABI.

Второй аргумент, то есть «предложение», дает вам возможность указать другое имя таблицы. Последний - определить тип таблицы, которую вы хотите использовать, на данный момент кажется, что есть только версия для i64, что означает 64-битную индексированную таблицу.

Другие типы, которые вы можете пройти, - это str для запроса по строке. i64, i64i64i64 и i128i128, все относятся к типу целочисленного primary_key, который в основном увеличивает количество возможных индексных номеров.

Определение типа владельца учетной записи

account_name owner = 0

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

Это определение настраиваемого типа, включенное в платформу EOS. Как бы он ни выглядел индивидуально, на самом деле он просто хранится как uint64_int.

Списки в вашей таблице

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

В этом примере у нас есть векторное отображение избирателя (account_name) и веса голоса (uint32_t).

std::vector<account_name, uint32_t> votes;

Первичные ключи
uint64_t primary_key() const { return id; }

Класс eosio::multi_index требует, чтобы ваша структура данных возвращала первичный ключ для вашей строки. Это необходимо, и это можно сделать, создав primary_key() метод на вашем struct. В этом примере показано, как мы приводим его к uint64_t, но это также может быть account_name, который, в свою очередь, является uint64_t замаскированным.

Серализация потока данных
EOSLIB_SERIALIZE( <StructName>, (field1)(field2)(field3))

Мне всегда было интересно, что конкретно это означает в примерах контрактов EOS. Зная, что это определенно макрос, я начал изучать код и лучше разбираться в системе. Глубоко покопавшись, я прочитал contracts/eosiolib/serialize.hpp и обнаружил, что он использует макрос `BOOST_PP_SEQ_FOR_EACH` (вот что он делает). Он в основном предоставляет дополнительные операторы структуры для сериализации и десериализации данных в базу данных multi_index и из нее.

Запросы, изменение и создание

База данных EOS Multi Index имеет некоторые функции для получения информации. Хотя функции не так обширны, как что-то вроде SQL-запроса, но он делает свои основы:

- Запрос записи с помощью .find
- Создание новых записей с помощью .emplace
- Изменение существующих записей с помощью .modify

Получение предметов

Для получения записи по ее первичному ключу мы просто запускаем:
auto itr = proposals.find(proposal_id)

Что возвращает вам итератор, который запросил элемент результата, кэшированный в частном порядке. Этот итератор предоставляет вам несколько весьма полезных функций для просмотра таблицы. Просматривая multi_index внутри EOS, мы видим, что у него есть несколько изящных методов оператора:

Итератор сам по себе может вернуть текущий объект путем разыменования объекта или как экземпляр объекта:

print(eosioitr->property) // reference
print((*itr).property) // instance
Proposal proposal = *itr // get object instance

Следующий и предыдущий объекты

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

auto nextitr = itr++;
auto previtr = itr--;

Под капотом. Для меня понимание предмета действительно помогает мне понять основные функции, а также обычно раскрывает их простоту. То же самое и с EOS: после рытья кода метод .find() просто запускает std::find_if function, которая проверяет, имеет ли зацикленный элемент правильный первичный ключ:

ptr._item->primary_key() == input_primary

Изменение предметов

Чтобы изменить объект, вы можете использовать метод .modify. Этот метод принимает следующие аргументы:
modify( const T& obj, uint64_t payer, Lambda&& updater )

Примером может быть:

auto iter = proposals.find(proposal_id);
// assert basically checks if iteration is at the end, meaning there is
// no value
eosio_assert(iter != proposals.end(), “Could not find proposal”);
proposals.modify( iter, _self, [&]( auto& proposal) {
 proposal.description = “New value”
});

В нашей первой строке мы возвращаем объект-итератор, который затем проверяется, находится ли список в конце таблицы multi_index, что означает отсутствие элемента.

После этого мы передаем этот объект-итератор в наш modify вызов, второй аргумент будет _self. Эта ссылка унаследована от класса eosio::contract, и обозначает account_name, развернувшего этот контракт.

Как видите, второй аргумент метода modify - это лямбда-функция, в которой вы получите ссылку на объект для обновления.

Создание новых предметов

Чтобы создать новый элемент, вы можете использовать метод .emplace из класса multi_index. Используются следующие аргументы:

emplace( uint64_t payer, Lambda&& constructor )

Как видите, первый аргумент - это снова payer ссылка. При каждом взаимодействии с EOS, как и с транзакцией ETH, есть кто-то, кто «платит» за хранение, мы рассмотрим это в следующей статье.

Пример вставки может быть:

auto new_proposal = proposals.emplace( _self, [&]( auto& proposal) {
 proposal.id = proposals.available_primary_key();
 proposal.owner = sender;
 proposal.description = description;
});

Собираем все вместе

Если объединить все это в один контракт, это будет выглядеть примерно так:

Мы продолжим рассмотрение 45_ примера голосования в следующих публикациях, чтобы продолжить работу над EOS.

Обновление:
Как мне сказали другие читатели, они хотели поделиться своими ресурсами, с которыми они работали, вот некоторые ресурсы для продолжения обучения:

Посмотрите это видео о разработке EOS:

Я более чем открыт для отзывов и советов по этому сообщению, так как это новая тема для меня, дайте мне знать!

PS: пожалуйста, подписывайтесь на меня, если вам понравилось ✌🏼