Развёртываем 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, нам пришлось отказаться от идеи использования сервиса в коммерческих проектах. Причин для этого было несколько. Основные из них:
- В Amazon Managed Blockchain была доступна лишь версия Hyperledger Fabric 1.2, а на момент написания этой статьи для построения корпоративных блокчейн-сетей используется версия 1.4. Это также не позволяет применять современные версии инструментов Node.js SDK;
- 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-серверов у нас будет четыре:
- Orderer, MySQL DB (для хранения информации)
- Parents organisation (Peer0, Peer1), CouchDB, Fabric-CA, CLI
- Hospital organisation (Peer0, Peer1), CouchDB, Fabric-CA
- 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-сервера:
- ec2–18–232–164–119.compute-1.amazonaws.com
- ec2–54–145–203–186.compute-1.amazonaws.com
- ec2–54–80–241–117.compute-1.amazonaws.com
- 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 с такими авторизационными данными:
(где
— это адрес первого сервера 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://
, где
— это адрес второго сервера 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://
, где
— это адрес третьего сервера 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://
, где
— это адрес четвертого сервера EC2.
Логин: kindergarten
, пароль: password
.
Заключение
Мы рассмотрели, как развернуть сеть блокчейн-приложения на нескольких виртуальных или физических серверах. Статья рассчитана на то, что вы знакомы с основами блокчейн-технологии, знаете, что такое смарт-контракты, и хотя бы поверхностно знакомы с фреймворком Hyperledger Fabric и его стандартным приложением fabric-samples.