Пояснительная записка к электронному журналу с использованием технологии Блокчейн, практическая часть: часть 1 и 2


2.1 Установка серверной части

2.1.1 Создание сервера:

Для этого захожу на https://vscale.io/panel и авторизовавшись, нажимаю
«Создать сервер».

Далее выбираю второй вариант за
400 рублей в месяц и нажимаю «создать сервер». Появляется окно с данными
и кнопкой «ок».

Копируем данные и идём в SSH клиент для дальнейшей работы с ним (Про SSH
клиент putty было написано в 1.2.1).

2.1.2 Работа на сервере:

После запуска putty.exe в папке WinSCP/putty мы видим стандартное окно
подключения, где вводим
root@ip:pass и нажимаем
open.

Правда после этого придётся ввести пароль ещё раз, но это ничего. Теперь
приступаем к настройке.

Для начала загрузил список пакетов, которые можно будет установить: sudo
apt-get update. После завершения выполняем установку Apache командой
sudo apt-get install apache2 и подтверждаем её, нажав y с Enter:

Когда и она завершилась, переходим к следующему шагу: включению
mod-rewrite и установке mysql. Это делается двумя командами:

sudo a2enmod rewrite

sudo apt-get install mysql-server.

Покажу скрин, но не факт, что в нём будет обе операции, но иначе их
будет слишком много. Далее
добавляем репозиторий php7 командой sudo apt-add-repository
ppa:ondrej/php

Но она у меня не сработала, т. к. не был установлен 1 пакет, который
позволяет добавлять репозитории. Ставим его командой $sudo apt
install software-properties-common

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

Далее обновляем список пакетов командой sudo apt-get update и
устанавливаем php7 так:

sudo apt-get install php7.0-cli php7.0-common libapache2-mod-php7.0
php7.0 php7.0-mysql php7.0-fpm php7.0-mbstring php7.0-gd php7.0-curl

2.1.3 Конфигурирование сервера и php

1\. Веб-сервер. Для этого переходим в папку apache (cd /etc/apache2) и
редактируем файл (sudo nano apache2.conf):

В конец вставляем

ServerName localhost ServerSignature Off

Задавая хост по умолчанию для самоопределения apache, и отключая
отображения версий сервера и системы на страницах ошибок.

2\. php (cd /etc/php/7.0/apache2). Файл php.ini (sudo nano php.ini):

Здесь включаем short\_open\_tag, заменив off на on, а также установив
memory\_limit на 128 и post\_max\_size на 64 МБ.

После всех действий сохраняем и устанавливаем PhpMyAdmin (Позволит
работать с базой данных). Вряд ли пригодится, но лишней не будет.
Для этого переходим в папку /usr/share (cd /usr/share), скачиваем sudo
wget
https://files.phpmyadmin.net/phpMyAdmin/4.8.5/phpMyAdmin-4.8.5-all-languages.zip,
ставим архиватор (sudo apt-get install unzip) и распаковываем скаченное
ранее: sudo unzip phpMyAdmin-4.8.5-all-languages.zip. Далее
переименовываем папку командой sudo mv 
phpMyAdmin-4.8.5-all-languages phpmyadmin, устанавливаем права (sudo
chmod -R 0755 phpmyadmin), и редактируем конфиг apache (sudo nano
/etc/apache2/sites-available/000-default.conf), прописав после
«DocumentRoot /var/www/html»:

Alias /phpmyadmin "/usr/share/phpmyadmin/"

\<Directory "/usr/share/phpmyadmin/"\>

Order allow,deny

Allow from all

Require all granted

\</Directory\>

Перезапускаем Apache (sudo service apache2 restart) и всё.

Дефолтная страница находится по адресу http://95.213.237.225.

И последним шагом устанавливаем
vsftpd, чтобы можно было работать на сервере через ftp: sudo apt-get
install vsftpd. После чего изменяем файл sudo nano /etc/vsftpd.conf. Тут
надо проверить значения параметров, чтоб они совпадали с описанными
ниже, а также чтоб все они не были закомментированы (Чтобы не было
“\#”):

anonymous\_enable=No

local\_enable=YES

write\_enable=YES

После редактирования файла перезапускаем vsftpd командой sudo service
vsftpd restart.

По сути всё, но я ещё создал второго пользователя, т. к. забыл
скопировать пароль от root.

2.1.4 Установка node.js, npm и pm2

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

Для начала устанавливаем Git командой sudo apt-get install git, а после
— выполняем sudo apt-get install -y nodejs и sudo apt-get install npm.
Проверяем их версию командой nodejs -v. У меня v8.10.0 – это старая
версия: необходимо обновить.

Чтобы сделать это вводим команды:

sudo npm cache clean -f

sudo npm install -g n

sudo n stable

Всё. Теперь перезапускаем сервер в панели управления vscale и проверяем
результат, введя node -v 11.8.0.

Далее проверяем версию npm командой npm -v: 6.5.0. Обновляемся на всякий
случай: sudo npm install npm -g. Повторный вызов npm -v показал, что
версия 6.7.0.

И последним шагом ставим pm2: sudo npm install pm2 -g.

pm2 – это модуль, который позволяет запускать скрипты в виде процессов,
т. е. Без необходимости держать открытым окно консоли.

2.1.5 Запуск системы

На этом общая часть закончилась, а начинается часть, связанная с
проектом электронного журнала.

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

Здесь я лишь покажу начальную часть: создание папки, загрузку скрипта
через ftp и его запуск через node, а потом — через pm2.

Поскольку у журнала будет веб часть, я решил разместить всё, что для
него нужно, в одной папке: varwww/html/journal. Для этого перехожу
в varwww/html командой cd и создаю journal командой mkdir. После чего
перехожу в неё (cd journal).

Создаю файл package.json командой sudo nano package.json с содержимым
{}, чтобы у nodejs было куда добавлять пакеты.

И после этого устанавливаю нужные nodejs модули (пакеты):

  1. sudo npm install nedb
  2. sudo npm install viz-world-js
  3. sudo npm install mysql

Результат:

Файл package.json имеет содержимое:

{

"dependencies": {

"mysql": "^2.16.0",

"nedb": "^1.8.0",

"viz-world-js": "^0.9.16"

}

}

Закидываю файл со скриптом. Вот каков вид папки:

После этого есть 3 варианта запуска скрипта:

node getData – запуск в стандартном варианте (терминал нельзя
закрывать). Выводит всё на экран (И ошибки, и результаты).

Node getData 1\> errors.log – выводит на экран ошибки, а в лог —
результат. Особенно удобен мне, т. к. на экране не всегда всё
можно хорошо услышать;

node getData 2\> errors.log – запуск с логами ошибок в файле и
результатом на экране;

pm2 start getData.js – запуск скрипта, как процесса (в отличие от
предыдущих вариантов позволяет закрывать окно терминала).

Я не буду скриншотить всё, т. к. иначе будет слишком много скриншотов,
поэтому покажу лишь 2 из них: node getData 2\> errors.log и pm2
getData.js

1\. Вариант с ошибками в лог файле и результатом в консоли:

Тут я показал только результат, т. к. в errors.log (файл ошибок), что
появился в папке со скриптом) ничего нет.

2\. Вариант с pm2.

Тут отображается после ввода команды лишь список процессов. Поскольку
getData.js единственный, только он:

2.2 Описание процесса разработки

Проект состоит из трёх частей:

  1. node.js часть: получение данных из блокчейна и добавление их в базу
    данных;
  2. Php: просмотр информации, её изменение и удаление.
  3. Локальная часть: страницы добавления данных в БЧ.

2.2.1 Конфигурационный файл: config.json

Перед тем, как переходить к разделам, скажу, что есть файл конфигов,
который используется и в node.js части, и в php.

Вот его содержимое по умолчанию:

{

"metodist": "denis-skripnik",

"db\_server": "localhost",

"db\_login": "root",

"db\_password": "",

"db\_name": "journal"

}

metodist имеет возможности админа (может добавлять всё, просматривать,
изменять и удалять тоже).

2.2.2 Node.js часть

Первый файл — это blockchainData.js. В нём находятся функции получения
данных и добавления их в БД.

Второй — database.js: функции работы с Mysql (позволяют не вводить кучу
раз методы NPM пакета Mysql, а использовать конкретные функции из этого
модуля);

blockchainData.js

В предпоследней строке вызывается runActions (функция без параметров):
отвечает за создание таблиц,

Последняя строка содержит

setInterval(() 😕> run(), 3000);

Вызывается функция run, которая проходит по блокам (касается блокчейна
Viz, куда добавляются данные).

Функция run

let bn = 0;

async function run() {

const props = await viz.api.getDynamicGlobalPropertiesAsync();

bn = bn || props.last\_irreversible\_block\_num;

for(; bn \< props.last\_irreversible\_block\_num; bn++){

await processBlock(bn);

}

}

Как видите, перед ней создаётся bn — это переменная, указывающая номер
блока, с которого производить парсинг блокчейна.

Константа props вызывает специальный метод, в котором находится
последний необратимый блок (блок, который не будет
откачен/изменён).

bn || props.last\_irreversible\_block\_num;

Эта строка получает непосредственно такой блок.

Ниже находится цикл, проходящий от текущего блока (в bn) до последнего
необратимого.

await processBlock(bn); вызывает функцию обработки операций, передаётся
в неё номер блока.

Функция processBlock

async function processBlock(bn) {

console.log("обработка блока",bn); // Вывод в консоль номера
обрабатываемого блока

const block viz.api.getBlockAsync(bn); // Получение операций
блока.

for(let tr of block.transactions) { // Цикл перебора транзакций в
блоке

for(let operation of tr.operations) { // Цикл прохода по операциям

const \[op, opbody\] // Назначаем переменные названию
операции (op) и основной части, содержащей различные данные
(opbody)

switch(op) { // Условие: если op

case "custom": // равно custom

if(opbody.id 'istr-i52') { // Идёт проверка, что id в opbody равна
istr-i52

await processCustom(block.timestamp, opbody); // Выполнить функцию
processCustom, передать в неё дату и время блока и тело операции.

}

break; // Прерывание цикла

default: // Пустое значение по умолчанию

//неизвестная команда

}

}

}

}

Блок состоит из транзакций. Транзакции — это то, что отправляет
конкретный пользователь и подписывает своим ключом. Транзакции
содержат в себе операции (их может быть множество, но они должны
использовать один и тот-же тип ключа). Так вот: Методист или
преподаватель добавляет какие-то данные: отправляется транзакция с
ними, содержит операции custom с нужными сведениями, например, о новом
предмете.

Функция получает номер блока, обращается через специальный метод и
получает транзакции, проходит циклом по ним, а при каждой итерации
этого цикла запускает ещё и цикл прохода по операциям. В каждой итерации
цикла операций происходит обработка того, что там есть: названия и тела
операции. Тело, в свою очередь, имеет множество полей (они зависят от
того, что-за операция). В custom есть поле id, по которому и
идентифицируем нужные нам данные.

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

Функция processCustom

async function processCustom(timestamp, custom\_body) {

let json // Переводим JSON в js

массив;

const table\_id // Получаем имя таблицы, чтобы знать, куда
добавлять данные.

const data // Получаем сами данные.

let lactors db.getData("lactors", "login",
custom\_body.required\_regular\_auths\[0\]); // // Ищем в поле login
таблицы lactors логин из специального поля операции.

if (lactors\[0\].login custom\_body.required\_regular\_auths\[0\] &&
table\_id 'assessments' || table\_id 'lesson\_topics') { //
Проверяем, что логин совпадает, а также таблица с оценками или
темами предметов.

let res db.addData(table\_id, data); // Добавляем в базу данных
данные в таблицу из table\_id.

console.log(res); // Выводим результат.

} else if (custom\_body.required\_regular\_auths\[0\]
config.metodist) { // Если логин из операции равен значению логина из
конфига.

let res db.addData(table\_id, data); // Добавляем данные в
базу.

console.log(res); // И выводим в консоль результат.

}

}

Пояснение: Тут думаю всё понятно. Единственное, скажу, что custom – это
операция отправки любых JSON данных в БЧ., поэтому их необходимо
преобразовывать.

Db – это модуль базы данных.

Общий вид JSOn – это примерно следующее:

\[table: “table\_id”, data: {}\].

runActions

Самая простая функция:

async function runActions() {

let result\_create db.createTables();

console.log(result\_create);

}

Вызывается функция из модуля db, которая создаёт таблицы, если их нет.
Также выводится результат.

В начале файла

const config // Подключение конфиг файла.

const db // Модуль базы данных.

const viz // Подключение npm пакета блокчейна
Viz.

Файл database.js

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

module.exports.addData // Экспорт метода, добавляющего данные
в базу.

module.exports.getData // Функция получения данных из БД.

module.exports.createTables // Экспорт функции создания
таблиц

Выше располагаются функции. Давайте пройдёмся по ним:

createTables (создание таблиц)

function createTables() {

let sql TABLE IF NOT EXISTS \[lactors\] (id integer NOT NULL
AUTO\_INCREMENT, login text); CREATE TABLE IF NOT EXISTS \[disciples\]
(id integer NOT NULL AUTO\_INCREMENT, login text); CREATE TABLE IF NOT
EXISTS \[lessons\] (id integer NOT NULL AUTO\_INCREMENT, name text,
lactors text); CREATE TABLE IF NOT EXISTS \[lesson\_topics\] (id integer
NOT NULL AUTO\_INCREMENT, date date, lesson text, topics text); CREATE
TABLE IF NOT EXISTS \[assessments\] (id integer NOT NULL
AUTO\_INCREMENT, date date, lesson text, disciple text, assessment
integer)."; // Переменная с SQL запросом на создание таблиц lactors,
disciples, lessons, lesson\_topics и assessments, если их нет.

return new Promise((resolve, reject) 😕> { // возвращаем результат в
Promise, чтобы можно было функцию использовать, как async (вызывать
через await).

connection.query(sql, (error, result) 😕> { // Отправляем запрос.

if(error) {

reject(error); // Если ошибка, возвращаем её.

} else {

resolve(result); // Иначе, результат.

}

});

  });

}

getData

function getData(table\_id, filde, value) { // Передаётся ей id таблицы,
поле и информация, которую в этом поле надо найти.

return new Promise((resolve, reject) 😕> {

connection.query('SELECT \* FROM \' + table\_id + '\ WHERE \' + filde

  • '\ = ' + value, (error, results, fields) 😕> { // Делаем запрос с
    использованием переменных, которые были переданы функции.

    if(error) {

    reject(error);

    } else {

    resolve(results);

    }

    });

    });

    }

Функция addData

function addData(table\_id, data) { // передаются ей название таблицы и
данные.

return new Promise((resolve, reject) 😕> {

connection.query('insert INTO ' + table\_id + ' SET ?', data, (error,
result, fields) 😕> { // Запрос с использованием переменных. Data
(данные) передаются в виде объекта javascript.

if(error) {

reject(error);

} else {

resolve(result);

}

});

});

}

В нач

але файла

const config = require('./config.json');

const mysql = require('mysql'); // Подключение NPM пакета Mysql.

let connection = mysql.createPool({

host : config.db\_host,

user : config.db\_login,

password : config.db\_password

, database : config.db\_name,

connectionLimit: 30

}); // Данные подключения к БД берутся из конфиг файла. Сюда они
забиваются, чтобы можно было использовать Mysql.

Package.json – файл с информацией о npm пакетах, которые нужны проекту

{

"dependencies": {

"mysql": "^2.16.0",

"viz-js-lib": "latest"

}

}

Из кода сего файла видно, что команда npm install в папке журнала
устанавливает mysql и viz-js-lib.

Всё

Благодарю за внимание. С вами был незрячий автор, программист и делегат @denis-skripnik. До встречи в новых постах.


Comments 3


Фонд БОД сделал репост.
Ваше творчество в ленте.
Наша лента в telegram.
)
Вы являетесь участником проекта БОД, поэтому все ваши посты
размещаются в ленте репостов фонда. Если не желаете получать
апвот фонда и этот комментарий, ставьте тег nobod.
06.08.2019 11:01
0

Здравствуйте, @denis-skripnik. Вы получили 100% апвот от UPRomo за сожженные GBG. Продвигали сей пост в очереди: @denis-skripnik.
Сервис прибавил к вашему посту примерно 123.175 GBG.

Инструкция по сжиганию для продвижения или задвигания постов.

Соглашение об использовании UPRomo.


Делегируйте СГ сервису UPRomo и способствуйте уменьшению количества GBG, что поможет выйти из кризиса, возобновить GBG и восстановить его цену, равную 1 МГ золота.

10.08.2019 06:54
0