Развёртываем Hyperledger Fabric 2.0 на AWS

от автора

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

В документации Hyperledger Fabric неплохо расписано создание блокчейн-сети на одной машине с помощью Docker, где каждый участник сети представляет собой отдельный контейнер. Но не описан процесс настройки сети на нескольких физических или виртуальных машинах. Об этом и пойдет речь в данной статье.

Наше блокчейн-приложение — это сервис для хранения некоторых медицинских данных детей школьного и дошкольного возраста. Данные должны быть неизменны. Они будут представлены в виде информации о вакцинации и о соглашении пациента с тем или иным доктором. В сети будут участники Parents (организация, которая представляет интересы родителей), Hospital (некая больница, с педиатрами которой родители могут заключать договор на обслуживание их ребенка/детей) и Kindergarten (некий детский сад, который сможет запрашивать отчеты о состоянии здоровья и вакцинации того или иного ребенка у больницы).

Amazon Managed Blockchain

У AWS есть сервис Amazon Managed Blockchain. Он позволяет развертывать блокчейн-сети с помощью пользовательских интерфейсов консоли AWS. Но, получив некоторый опыт работы с Amazon Managed Blockchain, нам пришлось отказаться от идеи использования сервиса в коммерческих проектах. Причин для этого было несколько. Основные из них:

  1. В Amazon Managed Blockchain была доступна лишь версия Hyperledger Fabric 1.2, а на момент написания этой статьи для построения корпоративных блокчейн-сетей используется версия 1.4. Это также не позволяет применять современные версии инструментов Node.js SDK;
  2. Amazon Managed Blockchain не поддерживает базу данных CouchDB, что затрудняет создание тех приложений, в которых индексируются хранимые данные.

Поэтому, наше мнение: для построения сетей с помощью фреймворка Hyperledger Fabric лучше использовать виртуальные или физические серверы.

О каналах приложения

В Hyperledger Fabric есть понятие «канала». Канал — это подсеть для проведения конфиденциальных транзакций. В нашем приложении будет два канала.

  • «parentshospital». Он предназначен для проведения транзакций между участниками организаций Parents и Hospital: как создание и изменение медицинских карт, создание соглашения с педиатром, подпись педиатром соглашения.
  • «parentshospitalkindergarten». В пределах этого канала участники организаций Parents и Hospital будут взаимодействовать с участниками организации Kindergarten. Также здесь будут создаваться отчёты на основании данных из медицинских карт.

Рабочее окружение

Разворачивать нашу блокчейн-сеть мы будем с помощью Docker Swarm — это родная система Docker для развертывания кластера хостов. Если вы никогда не работали с Docker, то сначала ознакомьтесь с этим продуктом и способом оркестрации контейнеров с помощью Docker Swarm. В документации хорошо описаны основы работы с этими инструментами.

Вся наша сеть будет расположена на серверах AWS EC2. Информация внутри блокчейн-сети будет храниться в CouchDB. Hyperledger Fabric поддерживает и базу данных LevelDB, однако CouchDB является хранилищем для JSON-документов, а не хранилищем значений ключей, поэтому позволяет индексировать содержимое документов. Также будем использовать Fabric Certificate Authority — это модульный компонент для управления сетевыми идентификаторами всех организаций и их пользователей. Он обеспечивает регистрацию участников сети и выпуск сертификатов.

EC2-серверов у нас будет четыре:

  1. Orderer, MySQL DB (для хранения информации)
  2. Parents organisation (Peer0, Peer1), CouchDB, Fabric-CA, CLI
  3. Hospital organisation (Peer0, Peer1), CouchDB, Fabric-CA
  4. Kindergarten organisation (Peer0, Peer1), CouchDB, Fabric-CA

Создание серверов EC2 на AWS

Нам для работы необходимы t2.medium-сервисы. Этот тип EC2-серверов имеет достаточные вычислительные мощности для установки всего необходимого программного обеспечения и работы с инструментом Hyperledger Fabric. В Configure Security Group устанавливаем All traffic, а Source — 0.0.0.0/0, ::/0.

Рис.1. Настройка Security Group в панели AWS.

Получили четыре EC2-сервера:

  1. ec2-18-232-164-119.compute-1.amazonaws.com
  2. ec2-54-145-203-186.compute-1.amazonaws.com
  3. ec2-54-80-241-117.compute-1.amazonaws.com
  4. ec2-52-87-193-235.compute-1.amazonaws.com

У вас, естественно, будут свои пути к серверам EC2.

Рис.2. Подготовленные для работы серверы EC2.

Установка необходимого ПО на серверы EC2

Теперь на каждый сервер EC2 нам необходимо установить Docker и Git. Для удобства откроем в терминале четыре вкладки. Зайдем в каждый сервис EC2 по SSH:

Терминал 1:

HOST1=ec2-18-232-164-119.compute-1.amazonaws.com ssh ec2-user@$HOST1 -i ./key-poc.pem 

Терминал 2:

HOST2=ec2-54-145-203-186.compute-1.amazonaws.com ssh ec2-user@$HOST2 -i ./key-poc.pem 

Терминал 3:

HOST3=ec2-54-80-241-117.compute-1.amazonaws.com ssh ec2-user@$HOST3 -i ./key-poc.pem 

Терминал 4:

HOST4=ec2-52-87-193-235.compute-1.amazonaws.com ssh ec2-user@$HOST4 -i ./key-poc.pem 

В каждом терминале выполним следующие команды:

sudo yum update -y sudo yum install -y docker sudo service docker start sudo docker info sudo yum install git sudo usermod -a -G docker ec2-user newgrp docker 

Теперь у нас установлены Docker и Git.

Сеть

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

git clone https://gitlab.nixdev.co/poc-blockchain/network.git 

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

Выполним эти действия на каждом из четырех серверов:

cd network && mkdir chaincode && cd chaincode git clone https://gitlab.nixdev.co/poc-blockchain/medical-contract.git git clone https://gitlab.nixdev.co/poc-blockchain/kindergarten-contract.git 

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

cd network/poc-network ./1_generate_connection_files.sh ./2_generating_channel_configuration.sh 

Теперь скопируем папки channel-artifacts и crypto-config на остальные три хоста в папку poc-network родительской директории network. Обратите внимание: при копировании на EC2-сервер организаций необходимо удалить из папки crypto-config/peerOrganizations сторонние сертификаты, которые относятся к работе иных организаций. Например, при копировании на хост Parents нам в этой папке необходимо оставить папку parents.poc-network.com, но удалить hospital.poc-network.com и kindergarten.poc-network.com.

Создание стека Docker Swarm

Чтобы контейнеры, которые принадлежат различным организациям и находятся на разных серверах EC2, имели возможность обращаться друг к другу, нам необходимо объединить их в стек. Давайте просмотрим наш файл network/poc-network/docker-compose-general.yaml. В нём прописана конфигурация сервисов, указано, на какие хосты будет развернут тот или иной сервис (ключ node.hostname), указаны псевдонимы (ключ aliases).

Нам необходимо инициализировать swarm в первом терминале:

docker swarm init docker swarm join-token manager 

Появится токен для присоединения другого EC2-сервера в стек. Что-то типа: docker swarm join --token SWMTKN-1-42ml0ohnnbidg8kflgp8xp9dkkus6mn1lslqc15hrxj4tk9e3q-5h4vbzbfk8p90n83oe08gbltf 172.31.46.214:2377.

Теперь мы можем выполнить в остальных терминалах:

docker swarm join --token SWMTKN-1-2xzco7t7txohnzd09318eczpbgmm8woex80byxptpt1jl5i2ar-bsg37h40xze1gaabg80i96gw2 172.31.38.245:2377 

В консоли появится сообщение:

This node joined a swarm as a manager. 

После того, как все три хоста присоединены к Swarm, мы сможем их увидеть в терминале первого хоста, выполнив команду:

docker node ls 

Рис.3. Список серверов в Docker Swarm.

В папке network/poc-network есть файл .env.template, в котором необходимо прописать hostname для каждого из хостов:

ORDERER=ip-172-31-38-245
PARENTS=ip-172-31-43-64
HOSPITAL=ip-172-31-38-130
KINDERGARTEN=ip-172-31-40-157

Чтобы сгенерировать .env файл, необходимо запустить файл ./3_env_gen.sh.

Теперь создадим сеть с драйвером overlay:

docker network create --driver overlay --attachable stage_byfn 

Запустим Swarm для создания стека на основании файла docker-compose-general.yaml:

env $(cat .env | grep ^[A-Z] | xargs) docker stack deploy -c docker-compose-general.yaml stage 2>&1 

Этой командой мы также устанавливаем переменные окружения, которые описаны в файле .env и которые необходимы для корректной работы сети.

Можете выполнить команду docker service ls в первом терминале. Вы увидите список всех сервисов, которые запущены на всех наших экземплярах EC2.

Рис.4. Список всех сервисов, которые были запущены на всех серверах EC2.

Если вы видите в своем терминале то же самое, что и на скриншоте, то всё отлично. Теперь запустим нашу сеть. Во втором терминале необходимо войти в контейнер CLI (ведь именно на втором хосте развернут этот контейнер):

docker exec -ti stage_cli.1.owni217t53m53efjtikb5oa2f /bin/bash 

Имя контейнера можно увидеть, выполнив в терминале команду docker ps.

В контейнере выполним все наши команды из файла 4_create_channels.sh, копируя их поочередно в терминал. В папке bin у нас находятся бинарники для создания сети:

  • peer channel create — создание каналов;
  • peer channel join — присоединение пира к каналу;
  • peer channel update — обновление конфигураций;
  • peer chaincode install — установка чейнкода;
  • peer chaincode instantiate — развернуть указанный цепной код в сети.

Теперь можно покинуть контейнер, выполнив команду exit.

Back-приложение для организации Parents

Установим приложение на второй хост:

cd ~ git clone https://gitlab.nixdev.co/poc-blockchain/back.git 

Также нам необходимо установить NodeJS и Gcc-c++ (компилятор):

curl -sL https://rpm.nodesource.com/setup_10.x | sudo bash - sudo yum install nodejs cd back sudo yum install gcc-c++ -y npm install 

Мы также можем зайти в нашу базу через adminer с такими авторизационными данными:

<HOST_1>:3306 (где <HOST_1> — это адрес первого сервера EC2, на котором хранится база данных)
dev
devpass
poc_database

Также необходимо подключить к базе данных наше API-приложение:

vim ~/back/config/config.json 

Присваиваем верное значение ключу host. Наше back-приложение имеет подготовленные миграции и сиды. Надо запустить их:

npx sequelize-cli db:migrate npx sequelize-cli db:seed:all 

В базе данных должны появиться таблицы. А в таблице organisations мы увидим три строки с нашими организациями — parents, hospital, kindergarten.

При генерировании сертификатов в самом начале мы получили для каждой организации на первом хосте файлы для соединения с сетью. Скопируем файл connection-parents.json с первого хоста на второй. Для этого откроем еще один терминал из папки, где лежит наш key, и выполним команды:

HOST1=ec2-18-232-164-119.compute-1.amazonaws.com HOST2=ec2-54-145-203-186.compute-1.amazonaws.com scp -i ./key-poc.pem -r ec2-user@$HOST1:~/network/poc-network/connection-parents.json ~ scp -i ./key-poc.pem ~/connection-parents.json ec2-user@$HOST2:~/network/poc-network 

Исправим exports.hostName в constants.js (значение для текущего хоста):

vim ~/back/constants.js 

Запустим наше приложение во втором терминале:

npm start 

В файле userGenerator.sh присвоим переменной HOST_2 верное значение:

vim ~/back/generators/userGenerator.sh 

Далее необходимо запустить скрипт, который создаст пользователей организации Parents:

./back/generators/userGenerator.sh parents 

Запускаем скрипт для генерирования медицинских карт:

node ~/back/generators/setCards.js 

В блокчейне создадутся две карты, которые также запишутся в SQL-базу данных в таблицу cards.

Back-приложение для организации Hospital

По аналогии с предыдущим back-приложением нам надо разместить файл для соединения с сетью на третьем хосте. Для этого в пятом терминале выполним:

scp -i ./key-poc.pem -r ec2-user@$HOST1:~/network/poc-network/connection-hospital.json ~ scp -i ./key-poc.pem ~/connection-hospital.json ec2-user@$HOST3:~/network/poc-network 

Склонируем наше приложение на третий хост:

cd ~ git clone https://gitlab.nixdev.co/poc-blockchain/back.git 

Установим NodeJS и Gcc-c++ (компилятор):

curl -sL https://rpm.nodesource.com/setup_10.x | sudo bash - sudo yum install nodejs cd back sudo yum install gcc-c++ -y npm install 

Исправим exports.hostName в constants.js (значение для текущего хоста):

vim ~/back/constants.js 

Запустим наше приложение в третьем терминале:

npm start 

В файле userGenerator.sh присвоим переменной HOST_3 верное значение:

vim ~/back/generators/userGenerator.sh 

Далее нам необходимо запустить скрипт, который создаст пользователей организации Hospital:

./back/generators/userGenerator.sh hospital 

У нас в базе теперь появился второй пользователь в таблице Users.

Back-приложение для организации Kindergarten

По аналогии с предыдущим back-приложением, нам надо разместить файл для соединения с сетью на третьем хосте. Для этого в пятом терминале выполним:

scp -i ./key-poc.pem -r ec2-user@$HOST1:~/network/poc-network/connection-kindergarten.json ~ scp -i ./key-poc.pem ~/connection-kindergarten.json ec2-user@$HOST4:~/network/poc-network 

Склонируем наше приложение на третий хост:

cd ~ git clone https://gitlab.nixdev.co/poc-blockchain/back.git 

Установим NodeJS и Gcc-c++ (компилятор):

curl -sL https://rpm.nodesource.com/setup_10.x | sudo bash - sudo yum install nodejs cd back sudo yum install gcc-c++ -y npm install 

Исправим exports.hostName в constants.js (значение для текущего хоста):

vim ~/back/constants.js 

Запустим наше приложение в третьем терминале:

npm start 

В файле userGenerator.sh присвоим переменной HOST_4 верное значение:

vim ~/back/generators/userGenerator.sh 

Далее нам необходимо запустить скрипт, который создаст пользователей организации Hospital:

./back/generators/userGenerator.sh kindergarten 

У нас в базе теперь появился третий пользователь в таблице Users.

Установка wkhtmltopdf на второй, третий и четвёртый серверы EC2

Важный момент. Для генерации PDF-отчета о состоянии здоровья ребенка в back-приложении используется библиотека wkhtmltopdf.

Нам необходимо установить libpng — официальную библиотеку для работы с растровой графикой в формате PNG. Библиотека платформонезависимая и состоит из функций, написанных на языке Си.

Первая команда установит wkhtmltox — библиотеку LGPLv3 с открытым исходным кодом для отрисовки HTML в PDF и различные форматы изображений с помощью механизма отрисовки QtWebKit:

wget https://downloads.wkhtmltopdf.org/0.12/0.12.5/wkhtmltox-0.12.5-1.centos7.x86_64.rpm sudo yum install -y wkhtmltox-0.12.5-1.centos7.x86_64.rpm 

Второй блок команд загрузит и развернет библиотеку libpng15:

wget https://sourceforge.net/projects/libpng/files/libpng15/older-releases/1.5.15/libpng-1.5.15.tar.gz/download -O libpng-1.5.15.tar.gz tar -zxvf libpng-1.5.15.tar.gz cd libpng-1.5.15 

Третий блок команд нужен для установки компилятора:

sudo yum groupinstall -y "Development Tools" ./configure --prefix=/usr sudo make install 

Еще необходимо установить LibTIFF:

sudo yum install -y libtiff 

Можем протестировать:

wkhtmltopdf https://majestic.cloud majestic.pdf 

Теперь вы сможете генерировать и просматривать PDF-документы.

Немного про Node SDK

NodeJS-инструменты для работы с сетью Hyperledger Fabric представлены в виде пакетов «fabric-ca-client -v 1.4.0» и «fabric-network» v 1.4.0». Все сервисы backend-приложения, которые с помощью Node SDK взаимодействуют с сетью, расположены в папке Services, в корне проекта.

Об этих инструментах и об их методах вы можете почитать в официальной документации.

Flow applications

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

Рис.5. Графическое описание бизнес-процессов в приложении.

Итак, в сети присутствуют несколько организаций: Parents, Hospital и Kindergarten.

Участник организации Parents создает электронные медицинские карты для двоих своих детей. Эти данные будут храниться (и дополняться) в блокчейн-сети. Далее родитель отправляет запрос на соглашение с педиатром, который будет наблюдать его детей до достижения ими совершеннолетия (на диаграмме — request for an agreement with a doctor).

Участник организации Hospital подписывает соглашение (на диаграмме — doctor signs an agreement).

Далее родитель отправляет запрос в детский сад с просьбой зачислить его ребенка (на диаграмме — request for kindergarten to receive a child).

Рис.6. Страница со списком доступных учебных заведений в личном кабинете родителя.

Детский сад видит запрос в списке новых запросов:

Рис.7. Страница со списком заявок на поступление в личном кабинете учебного заведения.

Детский сад перед принятием решения о зачислении ребенка должен убедиться в его удовлетворительном состоянии здоровья. Для этого детский сад отправляет запрос в поликлинику, в которой наблюдается этот ребенок (на диаграмме — child health report request). Запрос к педиатру выполняется автоматически после того, как запрос на зачисление в сад перемещается во вкладку «Accepted».

Рис.8. Страница со списком одобренных заявок на поступление в личном кабинете учебного заведения.

Педиатр видит запрос и формирует отчёт, в котором содержатся данные о здоровье ребенка (на диаграмме — child health report create).

Рис.9. Страница со списком заявок на создание отчета о состоянии здоровья ребенка в личном кабинете больницы.

Родитель видит, что педиатр сформировал отчёт…:

Рис.10. Страница в личном кабинете родителя, где отображается статус отчетов о состоянии здоровья ребенка.

… и принимает решение о предоставлении доступа учебному дошкольному заведению к просмотру и скачиванию отчёта (на диаграмме — give permission to view the report).

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

Родитель нажимает «Confirm»:

Рис.12. Уведомление о том, что выбранное учебное заведение получило разрешение на просмотр медицинского отчета.

В списке отчётов в приложении учебного заведения появляется информация о том, что отчёт сформирован и доступен к просмотру и скачиванию в формате PDF.

Рис.13. Ссылка на скачивание отчета в формате PDF в строке с одобренной заявкой.

Вот такой отчёт вы увидите в новой вкладке на своём компьютере:

Рис.14. Сформированный сотрудником больницы отчет о состоянии здоровья ребенка.

Создание медицинских карт и соглашения с педиатром, подпись соглашения

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

Первый сервер EC2:

node ~/back/generators/setCards.js 

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

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

node ~/back/generators/createAgreement.js 

Теперь это соглашение необходимо подписать пользователем, которого мы создавали для организации Hospital. Выполняем команду со второго хоста:

node ~/back/generators/signAgreement.js 

Наше соглашение подписано доктором и мы можем продолжать работать над нашим приложением. Далее нам необходимо установить frontend-приложение на второй, третий и четвёртый серверы EC2.

P.S.: Все команды для генерирования пользователей, карточек, соглашения и подписания соглашения вы можете найти в папке ~/back/generators.

Frontend-приложение для организации Parents

Выполним на втором хосте (где расположена организация Parents):

cd ~ git clone https://gitlab.nixdev.co/poc-blockchain/front.git 

Исправим имя хоста, на котором будет расположено наше frontend-приложение:

VUE_APP_API_BASE_URL='http://ec2-107-22-75-46.compute-1.amazonaws.com:3006/' 

Необходимо установить зависимости:

cd front npm install 

Также необходимо собрать приложение и запустить его на порте 8080:

docker build . -t my-app docker run -d -p 8080:80 my-app 

Наше приложение будет доступно по адресу: http://<HOST_2>:8080, где <HOST_2> — это адрес второго сервера EC2, на котором расположено наше приложение.

Логин: parents, пароль: password.

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

Рис.15. Информация о медицинских картах детей в личном кабинете родителя.

Frontend-приложение для организации Hospital

Выполним на втором хосте (где расположена организация Hospital):

cd ~ git clone https://gitlab.nixdev.co/poc-blockchain/front.git 

Исправим имя хоста, на котором будет расположено наше frontend-приложение:

VUE_APP_API_BASE_URL='http://ec2-3-91-238-161.compute-1.amazonaws.com:3006/' 

Необходимо установить зависимости:

cd front npm install 

Также необходимо собрать приложение и запустить его на порте 8080:

docker build . -t my-app docker run -d -p 8080:80 my-app 

Наше приложение будет доступно по адресу: http://<HOST_3>:8080, где <HOST_3> — это адрес третьего сервера EC2.

Логин: hospital, пароль: password.

Frontend-приложение для организации Kindergarten

Выполним на втором хосте (где расположена организация Kindergarten):

cd ~ git clone https://gitlab.nixdev.co/poc-blockchain/front.git 

Исправим имя хоста, на котором будет расположено наше frontend-приложение:

VUE_APP_API_BASE_URL='http://ec2-107-22-12-137.compute-1.amazonaws.com:3006/' 

Необходимо установить зависимости:

cd front npm install 

Также необходимо собрать приложение и запустить его на порте 8080:

docker build . -t my-app docker run -d -p 8080:80 my-app 

Наше приложение будет доступно по адресу: http://<HOST_4>:8080, где <HOST_4> — это адрес четвертого сервера EC2.

Логин: kindergarten, пароль: password.

Заключение

Мы рассмотрели, как развернуть сеть блокчейн-приложения на нескольких виртуальных или физических серверах. Статья рассчитана на то, что вы знакомы с основами блокчейн-технологии, знаете, что такое смарт-контракты, и хотя бы поверхностно знакомы с фреймворком Hyperledger Fabric и его стандартным приложением fabric-samples.

ссылка на оригинал статьи https://habr.com/ru/company/nix/blog/499214/