Погружение в технологию блокчейн: Взаимное страхование животных
Цикл статей «Погружение в технологию блокчейн»
1. Серия материалов, посвященных технологии Emer:
1.1. Секреты EmerCoin.
1.2. Децентрализованная нецензурированная система доменных имён.
1.3. Инфраструктура публичных ключей всемирного масштаба.
1.4. Децентрализованная беспарольная система безопасности.
2. Быстрые и безопасные транзакции.
3. Экосистема цифровой стоматологии.
4. Борьба с контрафактными товарами.
5. Взаимное страхование животных.
6. Loading…
Что такое ReGa Risk Sharing и Lexi
Компания ReGa Risk Sharing разработала платформу для взаимного страхования домашних животных с использованием технологий умных контрактов, идентификации по фотографии и скоринга. Робот по управлению рисками Lexi Bot помогает клиенту вступить в Клуб взаимопомощи владельцев домашних животных — Lexi Club и, после перечисления членского взноса в размере порядка 350 рублей в месяц, получать до 80% возмещения от стоимости ветеринарных услуг в случае внезапной болезни или несчастного случая c питомцем. Каждый из участников Клуба получает виртуальную карту Lexi Card, которая является идентификатором умного контракта, управляющего счетом участника Клуба в блокчейн Ethereum.
Распределенные финансовые продукты
Платформа ReGa Risk Sharing реализует распределенные финансовые продукты — продукты, которые можно выпускать и обслуживать без участия централизованных финансовых институтов — банков и страховых компаний. Для финансовых продуктов с низким размером инвестиции (кредита), которые можно условно назвать микро-финансовыми продуктами, существующая банковская система не может обеспечить адекватное соотношение стоимости и качества при заданном уровне риска. Это связано прежде всего с тем, что общие принципы регулирования не позволяют использовать современные технологии для оптимизации бизнес-процессов. Пример такого класса продуктов — микро-страхование, где средний чек составляет порядка 1,000 рублей и при этом урегулирование убытков требует значительных затрат со стороны страховой компании. В результате, договор с клиентом обычно составляется таким образом, чтобы практически исключить случаи выплат по страховым случаям. Решением может быть использование подходов взаимного страхования, когда сами клиенты объединяются в виртуальную страховую компанию, образует из своих взносов (страховых премий) капитал такой страховой компании и осуществляют выплаты по страховым случаям из фонда взаимного страхования. Платформа распределенных финансовых продуктов по сути является автоматизированной банковской/страховой системой для такого взаимного банка/страхового общества и предоставляет ряд сервисов, включая учет и хранения средств в блокчейн, оценку и управления рисками, автоматизацию бизнес-процессов и документооборота, подбор и оценку рисков поставщиков услуг для урегулирования страховых случаев и расчеты между участниками. Блокчейн является хранилищем капитала взаимного страхового общества, при этом доступ к счету контролирует умный контракт, который определяет правила пополнения и расходования средств согласованные и «подписанные» всеми участниками.
Архитектура распределенных финансовых продуктов
Архитектуру распределенных финансовых продуктов можно представить в виде модели, состоящей из 4 уровней: блокчейн, финансовые примитивы, финансовые продукты и приложения.
Уровень «Блокчейн» предоставляет набор базовых сервисов остальным уровням модели, включая механизм создания и выполнения умных контрактов, счета, финансовые сообщения, передачу закрытых сообщений, криптовалюту и собственно сам блокчейн, как распределенное и надежное хранилище данных. Предполагается, что блокчейн имеет два вида счетов — внешние или персональные счета, которые контролируются секретным ключом и счета контрактов, которые контролируются программой — умным контрактом, хранящейся в блокчейн вместе с балансом счета и состоянием своих внутренних переменных. Передача средств между счетами осуществляется путем посылки финансовых сообщений. Инициатором последовательности финансовых сообщений или транзакции может быть только владелец внешнего счета. Получателем может быть как внешний счет, так и счет контракта. В результате обработки финансового сообщения умным контрактом может быть создано новое финансовое сообщение. Таким образом, транзакция может состоять из целой последовательности сообщений или точнее из результатов их обработки и задействовать целое множество счетов, как внешних, так и счетов контрактов. С каждой транзакцией связана стоимость её выполнения и данная стоимость будет дебетована со счета инициатора транзакции.
Уровень «Финансовые примитивы» представляет собой набор «строительных» блоков для следующего уровня финансовых продуктов. Часть из этих сервисов реализуются на основе сервисов «Блокчейн», а часть представляет собой оффчейн примитивы, которые не связаны с хранением информации в распределенной базе данных. Так, мы не можем хранить скоринговую модель (карту) в блокчейне, так как в этом случае она становится доступна всем, включая потенциальных клиентов.
Скоринг по фотографии
Для построения скоринговой модели по фотографии клиента были использованы технологии, предоставленные компанией Microsoft: Microsoft Cognitive Service и Azure Machine Learning. С помощью сервиса Microsoft Face API (MS Cognitive) были обработаны порядка 15 000 фотографий потенциальных заемщиков, которым было отказано в получении потребительского кредита или кредит был одобрен по крайней мере одним из банков, подключенных к системе скоринга и андеррайтинга. По ним был получен полный набор возможных параметров: Face Landmarks и Face Attributes (
age
, gender
, headPose
, smile
, facialHair
и glasses
). Затем, были отброшены фотографии, где не было найдено лиц, либо найдено более одного. Таки образом отсеялось порядка 3% фотографий. Оставшийся массив данных был нормализован, то есть Landmarks
были преобразованы с учетом поворота головы (параметры Roll
и Yaw
), а затем все «лица» были пропорционально приведены к единому размеру — 100×100, что дало возможность сравнивать параметры лиц между собой. Каждой из обработанной фотографии был приписан признак Result = {0 - отказ | 1 - одобрение}
. После данной предварительной обработки и нормализации массив был преобразован в CSV файл и загружен в Azure Machine Learning.
К полученной таблице были применены ряд фильтров, включая Project
— выделение подмножества признаков и SMOTE
— дополнение выборки негативными результатами (Result = 0
). В результате количество строк в выборке увеличилось до 18 754, а количество признаков (колонок) составило 64. В качестве модели использовалась Two-Class Boosted Decision Tree
, обученная на 70% оцифрованных фотографий заемщиков и отказников, выбранных случайным образом из исходного массива (13 000 строк). После обучения оставшаяся часть массива (порядка 6 000 строк) были использованы для проведения скоринга и оценки аккуратности модели.
Получены следующие результаты:
Иерархическая структура групп по рискам
Для управления рисками платформа ReGa Risk Sharing использует трехуровневую иерархическую структуру групп эквивалентности по диапазонам значений скоринга. Верхний уровень — «Superpool» определяет минимальный допустимый уровень значения скоринга для всех участников сообщества. Следующий уровень — «Pool» «разбивает» максимальный диапазон на несколько поддиапазонов, а следующий уровень «Subpool» окончательно определяет группы по рисками.
Для любого нового члена сообщества вычисляется значение скоринга и, исходя из этого значения, вычисляется положение умного контракта члена сообществ в иерархической структуре. Основная идея группировки по рискам — это изолирование различных категории рисков друг от друга и возможность отслеживания эффективного значения риска на разных уровнях структуры. При этом, если одна из групп превышает заданные значения по рискам и оценочная стоимость сохранения группы выше, чем ликвидационная стоимость, то группа может быть расформирована и взносы в сообщество возвращены тем членам, которые покидают сообщество.
Структура пулов реализована в виде умных контрактов на языке Solidity для виртуальной машины Ethereum. Онлайновая версия компилятора доступна на GitHub. Стоит отметить, что Solidity позволяет множественное наследование. Ниже приведены интерфейсы классов, организующих иерархическую структуру.
Класс poolAccounts реализует учет движения средств по внутренней структуре счетов для организации банковского учета.pragma solidity ^0.4.6; contract poolAccounts { address public owner; int[11] public accounts; function changeBalance(int _amount, an _account) internal; function getBalance(an _account) internal constant returns(int _balance); function isValid() public constant returns(bool _valid); function posting(an _dr, an _cr, int _amount) public; function update(int _number, int _case) public; }
riskManager — вспомогательный класс сервиса по управлению рисками.pragma solidity ^0.4.6; contract riskManager { uint public risk; // current risk uint public minScore; // minimum accepting score uint public level; // risk manager level uint public cases; // number of cases per member function accept(regaMember _member) public constant returns(bool _accept, pool _pool); }
Класс poolMember — член пула, которым может быть, как член сообщества, так и пул среднего уровня.pragma solidity ^0.4.6; contract poolMember is poolAccounts { pool public parent; int public limit; function getPool(uint _level) public constant returns(pool _pool); function posting(an _dr, an _cr, int _amount); function update(int _number, int _case); function setParent(pool _parent) public; function loan(int _amount) public; function checkLimit(int _loan) public constant returns(bool); }
Классы pool и poolOfPools — реализуют методы работы с пулом и пулом пулов.POOLpragma solidity ^0.4.6; contract pool is riskManager, poolAccounts { bytes32 public name; poolMember[] public members; function insert(poolMember _member) public; function isMember(address _member) public constant returns(bool); function update(int _number, int _case); function getPool(uint _level) public constant returns(pool _pool); function lendingCheck(int _loan, poolMember _member) public constant returns(bool); function lend(int _loan, poolMember _member) public; function loan(int _amount, uint _level) public; }
POOLOFPOOLScontract poolOfPools is pool { function insert(poolMember _member) public; function push(pool _pool) public; function isMember(address _member) public constant returns(bool); function accept(regaMember _member) public constant returns(bool _accept, pool _pool) }
REGASUPERPOOLpragma solidity ^0.4.6; contract regaSuperPool is poolOfPools { function regaSuperPool(uint _minScore, address _owner) }
REGAPOOLpragma solidity ^0.4.6; contract regaPool is poolOfPools, poolMember { function regaPool(uint _minScore, address _owner); function getPool(uint _level) public constant returns(pool _pool); function loan(int _amount, uint _level) public; }
REGASUBPOOLpragma solidity ^0.4.6; contract regaSubPool is pool, poolMember { function regaSubPool(uint _minScore, address _owner, uint _cases); function getPool(uint _level) public constant returns(pool _pool); function loan(int _amount, uint _level) public; function insert(poolMember _member) public; }
Продукты
Для описания продуктов используется следующая иерархия.
Каждый распределенный финансовый продукт (LEVEL 1) описывается классом со следующими атрибутами:
- параметры продукта и калькулятор
- правила подбора продукта под требования (
needs
) и ограничения клиента - бизнес-процесс заключения договора (
underwriting process
) - бизнес-процесс обслуживания продукта (
support process
) - бизнес-процесс окончание договора (
closure process
) - правила управления рисками (
risk management rules
) - скоринговая карта (
scoring cards
) - правила отражения в банковской отчетности (
accounting rules
) - иерархическая структура пулов (
pools structure
)
Для каждого продукта определяются правила подбора данного продукта под требования и ограничения клиента. Процесс заключения договора описывает последовательность действий, которые должны быть выполнены системой для заключения контракта с клиентом. Для каждого клиента мы можем посчитать условия контракта используя параметры продукта и калькулятор. Например, для случая взаимного страхования животного, в зависимости от того кошка это или собака, калькулятор продукта посчитает стоимость контракта — Lexi Card Standart в месяц: 333 рубля — собака, 289 рубля — кошка.
Реализация приложения на Microsoft Azure
Уровень приложения для взаимного страхования домашних животных реализован в виде бота — Lexi Bot, который помогает клиенту вступить в Клуб взаимопомощи владельцев домашних животных и, после перечисления членского взноса, получать до 80% возмещения от стоимости ветеринарных услуг в случае внезапной болезни или несчастного случая c питомцем. Кроме этого, Lexi Bot поможет владельцу отыскать животное по фотографиям в социальных сетях, если оно потерялось, и организовать онлайн консультацию с ветеринарным врачом. Для получения Клубной карты Lexi Card владельцу достаточно открыть диалог с роботом в Facebook Messenger, Telegram, Slack или на сайте робота, загрузить собственную фотографию, фотографию питомца, получить тариф и перевести деньги на умный контракт участника Клуба.
Для получения возмещения достаточно записаться на прием к ветеринару через Lexi Bot, повторно сфотографировать животное в клинике и прислать роботу фотографии счета и чека. Робот автоматически сравнит полученные от владельца данные с данными, полученными из ветеринарной клиники, и проведет возмещение из фонда Клуба на счет участника Клуба. Интерфейс пользователя робота Lexi Bot разработан с использованием Microsoft Bot Framework и позволяет поддерживать сразу несколько каналов общения с клиентами с использованием единого сервера приложения. Идентификация животного осуществляется алгоритмом классификации на основе нейронной сети, позволяющим сравнивать разные фотографии одного и того же животного с точностью порядка 95%.
Ниже представлена архитектура решения.
Рассмотрим некоторые технические моменты реализации бота с использованием Microsoft Bot Framework на Microsoft Azure Bot Service.
Ethereum consortium blockchain
Несмотря на то, что описанной выше архитектуры взаимодействие бота с Ethereum осуществляется через сервер приложения, рассмотрим возможный способ взаимодействия между ботом и платформой Ethereum напрямую. Прежде всего, нам необходимо было реализовать генерацию и хранение ключей для подписание транзакция непосредственно в боте. Для этого можно использовать модуль
eth-lightwallet
вместе с модулем web3
— пример на GitHub.
var Web3 = require('web3');
var web3 = new Web3();
var lightwallet = require('eth-lightwallet');
var HookedWeb3Provider = require("hooked-web3-provider");
var keyStore = lightwallet.keystore;
var seed =
var host = ;
var pswd =
var contractAddr = ;
var abi =
Теперь мы можем реализовать метод инвестирования на счет смарт-контракта члена клуба.
blockchain.prototype.invest = function(acc, amount, success) {
if(web3 == null)
throw new Error('invest: Web3 provider is null');
var contract = web3.eth.contract(abi);
var instance = contract.at(contractAddr);
var gas = 500000;
var gasPrice = web3.toWei(20, "gwei");
var address = acc;
var value = web3.toWei(parseInt(amount), "ether");
instance.invest.sendTransaction(value, {gas: gas, gasPrice: gasPrice, value: value, from: address}, function(err, tnx) {
if (err) throw err;
else success(tnx);
});
};
module.exports = new blockchain();
Перед началом тестирования необходимо получить доступ к транзакционной машине Azure Ethereum Blockchain Consortium (в нашем случае regakrlby-tx0
), запустить на ней geth
и создать структуру контрактов.
Microsoft Cognitive Services
Для первоначального распознание типа домашнего питомца (кошка или собака) использовался Microsoft Cognitive Services. Для интеграции можно взять пример с GitHub. Ниже приведена часть диалога по получению фотографии животного.
bot.dialog('/image', session => {
if (hasImageAttachment(session)) {
var stream = getImageStreamFromUrl(session.message.attachments[0]);
captionService.getCaptionFromStream(stream)
.then(caption => handleSuccessResponse(session, caption))
.catch(error => handleErrorResponse(session, error));
}
else if(imageUrl = (parseAnchorTag(session.message.text) || (validUrl.isUri(session.message.text)? session.message.text : null))) {
captionService.getCaptionFromUrl(imageUrl)
.then(caption => handleSuccessResponse(session, caption))
.catch(error => handleErrorResponse(session, error));
}
else {
session.send("Did you upload an image? I'm more of a visual person. Try sending me an image or an image URL");
}
});
Обработка результата:
const handleSuccessResponse = (session, caption) => {
if (caption) {
session.send("I think it's " + caption);
}
else {
session.send("Couldn't find a caption for this one");
}
session.beginDialog('/');
}
Yandex money SDK
Для обмена рублей на криптовалюту необходимо интегрировать бот с рублевым электронным кошельком. В нашем случае был выбран сервис Yandex Деньги и использовался модуль
yandex-money-sdk
. Стоит отметить, что, устанавливая данный модуль из репозитория npm командой npm install yandex-money-sdk
мы получаем библиотеку с ошибкой, которую необходимо исправить: Wallet.getAccessToken = function (clientId, code, redirectURI, clientSecret, callback) {
var full_url = base.SP_MONEY_URL + "/oauth/token";
request.post({
"url": full_url,
"form": {
"code": code,
"client_id": clientId,
"redirect_uri": redirectURI,
"client_secret": clientSecret,
}
}, base.processResponse(callback)
);
};
В прототип функции
getAccessToken
модуля wallet.js
необходимо добавить строку: Wallet.getAccessToken = function (clientId, code, redirectURI, clientSecret, callback) {
var full_url = base.SP_MONEY_URL + "/oauth/token";
request.post({
"url": full_url,
"form": {
"code": code,
"client_id": clientId,
"redirect_uri": redirectURI,
"client_secret": clientSecret,
"grant_type": "authorization_code"
}
}, base.processResponse(callback)
);
};
Следующая сложность интеграции с Yandex Деньгами возникает из-за того, что бот в сервисе Microsoft Azure Bot Service представляет собой Azure Function. Для интеграции с
yandex-money-sdk
к стандартной функции messages
необходимо добавить новый HTTP trigger yandex
. Эта функция будет вызвана Yandex при прохождении двухфакторной аутентификации. Для добавления новой функции в корневой каталог бота нужно добавить новую директорию в нашем случае yandex
в которую необходимо поместить следующие файлы: drwxr-xr-x 5 sevriugin staff 170 Feb 13 12:16.
drwx------@ 12 sevriugin staff 408 Feb 13 12:15…
-rwxr-xr-x@ 1 sevriugin staff 258 Feb 15 11:12 function.json
-rwxr-xr-x@ 1 sevriugin staff 1426 Feb 15 11:13 index.js
-rw-r--r-- 1 sevriugin staff 530 Feb 13 21:05 package.json
Важно правильно описать новую функцию в файле
function.json
. Для входящего вызова необходимо установить уровень аутентификации равным anonymous
. Дело в том, что Yandex делает коллбэк: передает значение code
и если уровень аутентификации не равен anonymous
, то данный параметр будет интерпретироваться Microsoft Azure Bot Service, а не вашим обработчиком.{
"disabled": false,
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req"
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
Для передачи сообщений между функциями используем сервис очередей Azure Storage.
"use strict";
var config = require('../messages/config');
var azure = require('azure-storage');
var queueService = azure.createQueueService(config.azure_storage.account, config.azure_storage.key1);
queueService.createQueueIfNotExists('myqueue', function(error) {
if (!error) {
// Queue exists
console.info(`createQueueIfNotExists: Queue is created` + config.azure_storage.name);
}
});
module.exports = function(context, req) {
if (req.query.code || (req.body && req.body.code)) {
context.res = { body: "Please return to the chat…" };
}
else {
context.res = { status: 400, body: "Code is not found” };
}
queueService.createMessage('myqueue', req.query.sessionId + (req.query.code || req.body.code) , function(error) {
if (!error) {
console.info(`createMessage: Message is inserted`);
}
});
context.done();
};
Теперь в основной функции, которая отвечает за работу бота, необходимо осуществить несколько вызовов для привязки электронного кошелька к боту (пользователю бота). Прежде всего нужно отметить, что функция
messages
должна будет сохранить состояние диалога с пользователем перед вызовом yandex-money-sdk
. Для этого достаточно будет записать в базе данных session.message.address
и при вызове Yandex передать session.message.address.id
. Данный идентификатор будет возвращен Yandex при коллбэке функции yandex
. К сожалению, сервис очередей в Azure Storage Service работает без блокировки при проверке наличия сообщения в очереди, для этого пришлось реализовать поллинг в функции messages: function getMessage(error, serverMessages, id, cb) {
if (!error) {
if(((serverMessages && Array.isArray(serverMessages)) && serverMessages.length > 0) && serverMessages[0].messageText.startsWith(id)) {
var code = serverMessages[0].messageText.slice(id.length);
cb(code);
queueService.deleteMessage('myqueue', serverMessages[0].messageId, serverMessages[0].popReceipt, function(error) {
if (!error) {
// Message deleted
}
});
}
else {
setTimeout(function() {
queueService.getMessages('myqueue', function(error, serverMessages) {
if(!error) {
getMessage(error, serverMessages, id, cb);
}
});
}, 3000);
}
}
}
Почему Microsoft Azure
Для быстрого вывода на рынок нового продукта трудно придумать более удачный облачный сервис. Понятно, что есть проблемы и часть сервисов Azure работают еще не так стабильно как хотелось бы. Например, Microsoft Azure Bot Service — пока существует в превью-режиме, но огромное количество сервисов, которые доступны быстро и практически в любой конфигурации, перекрывают эти небольшие неудобства. Для нашего проекта особо важно было наличие сервисов блокчейн, к тому же Ethereum Blockchain as a Service полностью оправдал наши ожидания — быстрая активация и конфигурация, легкая интеграция с другим частями проекта. В общей сложности в проекте были использованы следующие сервисы: Azure Bot Service, Azure Storage, Microsoft Cognitive Service, Azure Machine Learning, Azure Ethereum Blockchain Consortium.
Заключение
Статья написана в момент, когда сервис по взаимному страхованию животных проходил тестирование. Промышленная конфигурация будет несколько отличатся от описанной выше архитектуры, в частности, вместо Microsoft Azure Bot Service будет использован Azure App Service. Наш проект на GitHub.
Об авторе
Сергей Севрюгин — CEO Bellwood Systems. В прошлом CEO DeltaBank и COO DeltaCredit. В настоящее время Сергей — Co-Founder ReGa Risk Manager. В 2015 году начал заниматься развитием решений на платформе Ethereum, первый прототип продукта создал в начале 2016 году: умные контракты на языке Solidity, сервер приложений NodeJS, Web App — JavaScript c AngularJS, мобильное приложение для iOS на языке Swift. С конца 2016 года делал прототип нового продукта — взаимное страхование животных на Azure с использованием Microsoft Bot Framework.
Напоминаем, что бесплатно попробовать Microsoft Azure можно здесь.