Публикация Создание приложения Blockchain с помощью C++ впервые появилась на Coinpedia Fintech News

Введение

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

Зачем нужно создавать блокчейн-приложение?

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

Эта статья представляет собой краткий 10-минутный экскурс в мир разработки блокчейна на языке C++.

Основы блокчейна

Блокчейн — это цифровая цепочка, состоящая из отдельных защищенных и защищенных от несанкционированного доступа единиц, называемых блоками. Каждый блок содержит свои метаданные и обозначенную информацию о транзакции. До сих пор мы просто создавали отдельные блоки, верно?! Как бы вы попытались установить связь между каждым блоком осмысленным образом? Ответ заключается в связывании каждого блока с его предыдущим блоком с помощью уникальных случайных криптографических функций, известных как хэш. Каждый блок имеет свой собственный хэш, который является первичным ключом, и вы можете связать все блоки посредством хэширования в хронологическом порядке, образуя цепочку, которая представляет всю историю транзакций в сети.

C++ в блокчейне

C++ — один из самых мощных языков, используемых в блокчейне, благодаря своей скорости, гибкости и контролю. Он творит чудеса при работе со сложными системами, разработкой игр и финансовыми приложениями. Без сомнения, это самый универсальный язык!

C++ блистает в блокчейне по нескольким причинам. Он позволяет разработчикам создавать эффективные системы блокчейна благодаря низкоуровневому управлению памятью, которое обеспечивает точный контроль. Мы все знаем, насколько огромна и безопасна сеть Bitcoin. Представьте, насколько сложным должно быть ее ядро, поскольку ему необходимо обрабатывать бесчисленное количество транзакций. Поэтому для решения этой сложной задачи был выбран C++. Есть несколько важных приложений, разработанных с использованием C++, таких как Bitcoin, Lifecoin, Ripple, Monero и EOS.

Почему C++ — идеальный язык для разработки блокчейна?

  • Более быстрые вычисления

  • Высокая производительность

  • Эффективное управление памятью

  • Объектно-ориентированные функции

  • Поддерживает многопоточность

  • Контроль над системными ресурсами

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

Понимание концепций блокчейна с помощью C++

Транзакции: В блокчейне транзакции являются сутью, которая управляет всей системой. Отдельные блоки подобны безопасным хранилищам, которые хранят престижную информацию об обмене и стоимости транзакций вместе с участниками. Эти транзакции являются фундаментальными записями, которые рассказывают историю о том, кто чем обменивался, с кем и когда.

Основы блокчейна, которые вам следует знать

Децентрализация: Децентрализация — причина, по которой блокчейн выделяется во всей технологической сфере. Что такое децентрализация? Это свойство блокчейна, при котором ни одна организация не контролирует всю базу данных. Это делает систему устойчивой к сбоям и препятствует любым видам предвзятости. Каждое устройство-участник (узел) поддерживает копию блокчейна, обеспечивая прозрачность и предотвращая централизованный сбой или манипуляцию.

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

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

До сих пор вы, должно быть, поняли все основы блокчейна, верно? Хватит теории! Давайте теперь перейдем к практической части. Готовы испачкать руки?

В этом разделе мы проведем вас через весь процесс разработки простого блокчейн-приложения. От настройки среды до тестирования и развертывания.

1.Настройка среды разработки C++

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

Установка компилятора C++

Давайте начнем с понимания того, что такое компилятор.

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

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

GCC (коллекция компиляторов GNU):

Linux/MacOS:

Откройте терминал и введите команды, указанные ниже.

a)Ubuntu/Debian:sudo apt updatesudo apt install build-essentialb)Fedora sudo dnf install gcc gcc-c++c)MacOS(инструменты командной строки)xcode-select –install

Windows: Для пользователей Windows проект MinGW-w64 является отличным выбором, поскольку он представляет собой порт GCC (GNU Compiler Collection) для Windows, предлагая всю мощь GCC в среде Windows.

Шаги по установке:

  • Загрузите установщик, посетив официальный сайт MinGW-w64.

  • Запустите установщик после загрузки.

  • Выберите подходящую архитектуру в соответствии с вашими потребностями

  • Следуйте инструкциям мастера для завершения.

  • Обновите систему (это необязательный, но рекомендуемый шаг).

  Лязг:

Linux/MacOS: sudo apt install clang (clang также уже установлен в MacOS) Fedora: sudo dnf install clang Windows: Clang можно установить с помощью MinGW или через установщик проекта LLVM

MSVC (Microsoft Visual C++):

MSVC (Microsoft Visual C++) является неотъемлемым компонентом Visual Studio, надежной интегрированной среды разработки (IDE), разработанной корпорацией Microsoft. Visual Studio предоставляет полный набор инструментов для разработки, тестирования и развертывания приложений, а его установка автоматически настроит MSVC в вашей системе.

Проверьте установку, используя следующие команды в терминале или командной строке:

g++ –version  # Для GCCclang –version  # Для Clangcl  # Для MSVC

Выбор IDE

Интегрированная среда разработки (IDE) повышает производительность, предлагая такие инструменты, как автодополнение кода, отладка и управление проектами в едином интерфейсе. Ниже приведены некоторые широко используемые IDE для разработки на C++:

Visual Studio: Загрузите Visual Studio с официального сайта.

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

CLion: Установка и настройка:

CLion — популярная среда разработки, работающая на базе JetBrains, но требующая подписки, однако предоставляющая бесплатные пробные версии.

предоставляет бесплатные пробные версии.

Visual Studio Code: установка и настройка расширений для разработки на C++.

Установка необходимых библиотек

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

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

2. Создание простого блокчейна с помощью C++

Прежде чем приступить к написанию кода, давайте разберемся с компонентами класса блока.

Компоненты Blockclass

  • Индекс — это целое число, которое хранит и поддерживает отсортированный порядок блоков в хронологическом порядке.

  • Временная метка: временная метка хранит момент создания блока в виде строки.

  • Транзакции: Транзакции хранят информацию об обмене между участниками и состояние блокчейна на тот момент.

  • Предыдущий хэш и хэш: Предыдущий хэш хранит криптографический хэш предыдущего блока, тогда как хэш представляет собой строку криптографической информации, перемешанную или хэшированную.

  • Nonce: Целое число, используемое в алгоритме консенсуса Proof of Work (PoW). Действует как счетчик, который увеличивается для поиска допустимого хеша, соответствующего целевой сложности. Nonce имеет решающее значение для процесса майнинга в PoW, где майнеры соревнуются, чтобы найти nonce, который генерирует хеш с определенным количеством начальных нулей.

Давайте теперь реализуем все функции в коде:

class Block {public:    int index;     std::string timestamp;     std::vector<Transaction> transaction;     std::string previousHash;     std::string hash;     int nonce; // Для PoW    // Конструктор    Block(int idx, std::string time, std::vector<Transaction> txs, std::string prevHash) {        index = idx;         timestamp = time;        transaction = txs;         previousHash = prevHash;         nonce = 0;         hash = calculateHash(); // Хэш текущего блока    }    // Метод вычисления хеша блока    std::string calculateHash() {         std::stringstream ss;         ss << index << timestamp << previousHash << nonce;         // Добавить данные транзакции и любые дополнительные сведения к вычислению хэша return sha256(ss.str()); // Заполнитель для фактической хэш-функции} // Метод для майнинга блока void mineBlock(int difficulty) { std::string target(difficulty, ‘0’); // Создать строку целевого хеша while (hash.substr(0, difficulty) != target) { nonce++; hash = calculateHash(); }     }};

После того, как вы закончите с определением blockclass и его атрибутов, вы можете перейти дальше и создать блок генезиса. Блок генезиса — это первый блок в блокчейне, который необходимо инициализировать, и он имеет индекс, равный нулю. После определения блока генезиса вы можете продолжить и добавить новые блоки в свой блокчейн, используя метод addblock(). Ниже вы можете найти код:

класс Blockchain {public:    std::vector<Block> chain;     Blockchain() {        chain.push_back(createGenesisBlock());     }    Блок createGenesisBlock() {        return Block(0, “01/01/2024”, “Genesis Block”, “0”);     }    Блок getLatestBlock() {         return chain.back();    }    void addBlock(Block newBlock) {         newBlock.previousHash = getLatestBlock().hash;         newBlock.hash = newBlock.calculateHash();         chain.push_back(newBlock);     }};

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

класс Транзакция {public:    std::string отправитель;     std::string получатель;     double сумма;     std::string transactionID;     // Конструктор    Транзакция(std::string snd, std::string rcp, double amt, std::string txID) {         отправитель = snd;         получатель = rcp;         сумма = amt;          transactionID = txID;    }    // Метод проверки транзакции    bool validateTransaction() {        // Реализация логики проверки        return true; // Заполнитель     }};

3.Реализация механизмов консенсуса в C++

 До сих пор вы завершили 25% процесса построения. Теперь вы двигаетесь вперед и внедряете механизмы консенсуса для своего блока, который является основой всего приложения.

Доказательство работы

Proof of Work (PoW) — это механизм консенсуса, с помощью которого участники сети блокчейн/майнеры должны найти решение сложной вычислительной математической задачи, прежде чем они смогут добавить новый блок в цепочку. По сути, это процесс нахождения определенного числа, называемого nonce, которое объединяется с данными блока, его хешем и другими данными для генерации значения хеша, которое начинается с определенного количества начальных нулей. Это делает процесс эффективным и защищает сеть от вредоносных атак.

В C++ вы можете реализовать Proof of Work, добавив атрибут proof и метод proof of work в класс Block. Вот как это можно сделать:

#include <iostream>#include <sstream>#include <ctime>#include <string>#include <vector>#include <openssl/sha.h>использование пространства имен std;string sha256(const string str) {    unsigned char hash[SHA256_DIGEST_LENGTH];     SHA256_CTX sha256;     SHA256_Init(&sha256);     SHA256_Update(&sha256, str.c_str(), str.length());     SHA256_Final(hash, &sha256);     stringstream ss;    for(int i = 0; i < SHA256_DIGEST_LENGTH; i++) {        ss << hex << setw(2) << setfill(‘0’) << (int)hash[i];     }    return ss.str();}class Block {public:    int index;     string data;     string previousHash;     string hash;     long proof;     time_t timestamp;    Block(int idx, string d, string prevHash) {        index = idx;         data = d;         previousHash = prevHash;         timestamp = time(nullptr);         proof = 0;         hash = calculateHash();     }    string calculateHash() const {        stringstream ss;        ss << индекс << временная метка << данные << предыдущийХеш << доказательство;         return sha256(ss.str());     }    void proofOfWork(int difficulty) {         string target(difficulty, ‘0’);         do {             proof++;              hash = calculateHash();         } while (хеш.substr(0, difficulty) != target);    }};класс Blockchain {public:    vector<Block> chain;     int difficulty;     Blockchain(int diff) {         трудность = diff;          chain.emplace_back(Block(0, “Genesis Block”, “0”));    }    void addBlock(string data) {        Block newBlock(chain.size(), data, chain.back().hash);         newBlock.proofOfWork(difficulty);        если (isValidProof(newBlock)) {            chain.push_back(newBlock);         }    }    bool isValidProof(const Block& block) const {        return block.hash.substr(0, difficulty) == string(difficulty, ‘0’);     }};

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

4. Создание простого API блокчейна с помощью C++

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

Настройка среды API

Установите и настройте инструменты, необходимые для создания API на C++, как указано в таблице ниже:

Создание API

#include <cpprest/http_listener.h>#include <cpprest/json.h>#include «blockchain.h»используя пространство имен web;используя пространство имен http;используя пространство имен utility;используя пространство имен http::experimental::listener;Блокчейн blockchain(4); // уровень сложности 4void handleGet(http_request request) {    json::value response = json::value::array();     int i = 0;     for (auto& block : blockchain.chain) {        json::value block_json;        block_json[U(“index”)] = json::value::number(block.index);         block_json[U(“data”)] = json::value::string(block.data);         block_json[U(“previousHash”)] = json::value::string(block.previousHash);         block_json[U(“hash”)] = json::value::string(block.hash);         block_json[U(“proof”)] = json::value::number(block.proof);        block_json[U(“timestamp”)] = json::value::number(block.timestamp);         response[i++] = block_json;    }    request.reply(status_codes::OK, response);}void handlePost(http_request request) {    request.extract_json().then([&](json::value requestData) {        auto data = requestData[U(“data”)].as_string();blockchain.addBlock(data);request.reply(status_codes::OK, U(“Блок успешно добавлен”));}).wait();}int main() {http_listener listener(U(“http://localhost:8080”));listener.support(methods::GET, handleGet);listener.support(methods::POST, handlePost);try {listener.open().wait();cout << “Прослушивание на http://localhost:8080” << endl;while (true);} catch (exception const& e) {cerr << e.what() << endl;    }return 0;}

handleGet извлекает весь блокчейн в формате JSON.

handlePost добавляет новый блок в блокчейн, используя данные из запроса POST.

Запуск и тестирование приложения

Запуск приложения

Как только вы закончите с основными функциями кода в соответствии с циклом разработки ПО, вам нужно перейти к самому важному и неизбежному этапу компиляции и тестирования всего приложения. Это наиболее важно для подтверждения того, что компоненты в приложении работают так, как и ожидалось.

Скомпилируйте код:g++ -o blockchain_api blockchain_api.cpp -lboost_system -lcrypto -lssl -lcpprestЗапустите исполняемый файл:./blockchain_api

Приведенный выше код запускает сервер API по адресу http://localhost:8080.

Тестирование с помощью Postman

  • Протестируйте конечные точки API с помощью Postman или curl:

  • Добавить блок:

  • Метод: ПОСТ

  • URL-адрес: http://localhost:8080

  • Тело: формат JSON

{  «data»: «Это новый блок»}

Просмотреть блокчейн:

  • Метод: ПОЛУЧИТЬ

  • URL-адрес: http://localhost:8080

Пример добавления блока и просмотра блокчейна с использованием API, созданного на C++.

void handleGet(http_request request) {    json::value response = json::value::array();     int i = 0;     for (auto& block : blockchain.chain) {        json::value block_json;         block_json[U(“index”)] = json::value::number(block.index);         block_json[U(“data”)] = json::value::string(block.data);        block_json[U(“previousHash”)] = json::value::string(block.previousHash);         block_json[U(“hash”)] = json::value::string(block.hash);         block_json[U(“proof”)] = json::value::number(block.proof);         block_json[U(“timestamp”)] = json::value::number(block.timestamp);         response[i++] = block_json;     }    request.reply(status_codes::OK, response); }void handlePost(http_request request) {    request.extract_json().then([&](json::value requestData) {        auto data = requestData[U(“data”)].as_string();blockchain.addBlock(data);request.reply(status_codes::OK, U(“Блок успешно добавлен”)) }).wait();}

Функция handlePost обрабатывает добавление блока, извлекая данные из тела JSON и добавляя новый блок в блокчейн.

Функция handleGet извлекает весь блокчейн и отправляет его обратно в виде ответа JSON.

6.Живой пример создания приложения блокчейна с помощью C++

Пошаговое выполнение

Шаг 1: Создайте класс Block с необходимыми атрибутами, используя синтаксис C++.

#include <iostream>#include <ctime>#include <string>#include <sstream>#include <vector>#include <openssl/sha.h>используя пространство имен std;класс Block {public:    int index;     string data;     string previousHash;     string hash;     длинное доказательство;     time_t timestamp;    Block(int idx, const string& data, const string& prevHash)        : index(idx), data(data), previousHash(prevHash), proof(0), timestamp(time(nullptr)) {         hash = calculateHash();     }    string calculateHash() const {         stringstream ss;         ss << index << timestamp << data << previousHash << proof;         return sha256(ss.str());    }    void proofOfWork(int difficulty) {         string target(difficulty, ‘0’);         do {             proof++;              hash = calculateHash();         } while (hash.substr(0, difficulty) != target);    }private:    string sha256(const string& input) const {        unsigned char hash[SHA256_DIGEST_LENGTH];         SHA256_CTX sha256;         SHA256_Init(&sha256);         SHA256_Update(&sha256, input.c_str(), input.size());         SHA256_Final(hash, &sha256);  stringstream ss;        для (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {            ss << hex << setw(2) << setfill(‘0’) << (int)hash[i];         }        return ss.str();     }};

Шаг 2: Реализуйте метод calculateHash.

#include <iostream>#include <sstream>#include <iomanip>#include <openssl/sha.h>class Block {public:    int index;     std::string data;     std::string previousHash;     std::string hash;     long proof;     time_t timestamp;    Block(int idx, const std::string& data, const std::string& prevHash)        : index(idx), data(data), previousHash(prevHash), proof(0), timestamp(time(nullptr)) {         hash = calculateHash();     } std::string calculateHash() const {        std::stringstream ss;         ss << index << timestamp << data << previousHash << proof;         return sha256(ss.str());    }private:    std::string sha256(const std::string& input) const {        беззнаковый символьный хэш[SHA256_DIGEST_LENGTH];         SHA256_CTX sha256;         SHA256_Init(&sha256);         SHA256_Update(&sha256, input.c_str(), input.size());         SHA256_Final(хэш, &sha256);        std::stringstream ss;         for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {             ss << std::hex << std::setw(2) << std::setfill(‘0’) << (int)hash[i];         }         return ss.str();     }};

Шаг 3: Определите класс Blockchain и инициализируйте его с помощью генезис-блока.

класс Blockchain {public:    Blockchain(int difficulty)        : difficulty(difficulty) {         chain.emplace_back(Block(0, “Genesis Block”, “0”));     }    void addBlock(const string& data) {         Block newBlock(chain.size(), data, chain.back().hash);         newBlock.proofOfWork(difficulty);         chain.push_back(newBlock);    }    const Block& latestBlock() const {        return chain.back();     }    vector<Block> chain;private:    int difficulty;};

Шаг 4: Реализуйте метод calculateHash.

#include <iostream>#include <sstream>#include <iomanip>#include <openssl/sha.h>class Block {public:    int index;     std::string data;     std::string previousHash;     std::string hash;     long proof;     time_t timestamp;    Block(int idx, const std::string& data, const std::string& prevHash)        : index(idx), data(data), previousHash(prevHash), proof(0), timestamp(time(nullptr)) {         hash = calculateHash();     }    std::string calculateHash() const {        std::stringstream ss;         ss << index << timestamp << data << previousHash << proof;         return sha256(ss.str());    }private:    std::string sha256(const std::string& input) const {        беззнаковый символьный хэш[SHA256_DIGEST_LENGTH];         SHA256_CTX sha256;         SHA256_Init(&sha256);         SHA256_Update(&sha256, input.c_str(), input.size());         SHA256_Final(хэш, &sha256);        std::stringstream ss;         for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {             ss << std::hex << std::setw(2) << std::setfill(‘0’) << (int)hash[i];         }         return ss.str();     }};

Шаг 5: Определите класс Blockchain и инициализируйте его с помощью генезис-блока.

class Blockchain {public:    Blockchain(int difficulty)        : difficulty(difficulty) {         chain.emplace_back(Block(0, “Genesis Block”, “0”));     }    void addBlock(const string& data) {         Block newBlock(chain.size(), data, chain.back().hash);         newBlock.proofOfWork(difficulty);         chain.push_back(newBlock);    }    const Block& latestBlock() const {        return chain.back();     }    vector<Block> chain;private:    int difficulty;};

Шаг 6: Настройте среду API для обработки запросов с использованием подходящей библиотеки C++.

#include <cpprest/http_listener.h>#include <cpprest/json.h>использование пространства имен web;использование пространства имен web::http;использование пространства имен web::http::experimental::listener;класс BlockchainAPI {public:    BlockchainAPI(const string& address, Blockchain& blockchain)     : listener(http_listener(U(address))), blockchain(blockchain) {        listener.support(methods::GET, std::bind(&BlockchainAPI::handleGet, this, std::placeholders::_1));listener.support(methods::POST, std::bind(&BlockchainAPI::handlePost, this, std::placeholders::_1));void start() {listener.open().wait();         cout << “API блокчейна запущено…” << endl;     }Private:http_listener listener;    Blockchain& blockchain;void handleGet(http_request request) {json::value response = json::value::array();int i = 0;for (const auto& block : blockchain.chain) {json::value block_json;block_json[U(“index”)] = json::value::number(block.index);block_json[U(“data”)] = json::value::string(block.data);block_json[U(“previousHash”)] = json::value::string(block.previousHash);block_json[U(“hash”)] = json::value::string(block.hash);block_json[U(“proof”)] = json::value::number(block.proof);block_json[U(“timestamp”)] = json::value::number(block.timestamp);response[i++] = block_json;  }        request.reply(status_codes::OK, response);     }void handlePost(http_request request) {request.extract_json().then([&](json::value requestData) {string data = requestData[U(“data”)].as_string();blockchain.addBlock(data);request.reply(status_codes::OK, U(“Блок успешно добавлен”));}) . wait () ; }} ;

Шаг 7: Протестируйте приложение, создав новый блок и проверив блокчейн с помощью Postman или curl.

Main:int main() {    Blockchain blockchain(4);  // Уровень сложности    BlockchainAPI api(“http://localhost:8080”, blockchain);     api.start();     return 0;}Testing:curl -X POST http://localhost:8080 -H “Content-Type: application/json” -d ‘{“data”:”Это новый блок”}’

Начало разработки блокчейна с использованием C++ — это больше, чем просто кодирование; речь идет о создании основополагающих элементов децентрализованных систем, которые могут произвести революцию в различных отраслях.

Подводя итог, мы рассмотрели все: от основ программирования на C++ для блокчейна до развертывания и тестирования приложения.

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

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