Погружение в технологию блокчейн: Экосистема цифровой стоматологии

Представляем вторую статью из серии «Погружение в технологию блокчейн». В этом материалы вы узнаете о медицинском проекте Digital Dentistry Exchange, который представляет из себя экосистему цифровой стоматологии.

Мы расскажем о его технологических особенностях, ответим на самые частые вопросы о смарт-контрактах и поделимся видением команды о том, какое будущее у технологии блокчейн.

5dfa7862f02e45deb35e77e05d0fb3bb.jpg

Цикл статей «Погружение в технологию блокчейн»


1. Погружение в технологию блокчейн: Секреты EmerCoin.
2. Погружение в технологию блокчейн: Быстрые и безопасные транзакции.
3. Погружение в технологию блокчейн: Экосистема цифровой стоматологии.
4. Loading…

Проблема распределения ответственности и повышения качества комплексных услуг в сфере стоматологии


В современной цифровой стоматологии существует направление под названием CAD/CAM (Computer Aided Design и Computer Aided Manufacturing). Оно применяется для создания таких зуботехнических конструкций, как коронки, виниры или вкладки (очень крутой вид пломб). Процесс производства с помощью ЭВМ состоит из нескольких этапов:

1. Врач производит подготовку зуба к установке зуботехнической конструкции, снимает оттиск и формирует заказ-наряд:

8621c37c30ca41bf9191c6a0fa0642ec.png

2. Врач договаривается о цене с пациентом, идет предоплата.

3. Оттиск сканируется и получается цифровая трехмерная модель зубов пациента:

54485b09eef545d08435ef4493f4d726.png

4. С помощью системы специализированного проектирования (САПР) на базе этой модели конструируется дизайн зуботехнической конструкции с учетом пожеланий пациента и врача.

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

6. Изделие дезинфицируется и устанавливается пациенту.

6301cf253f354b1fb1927dba393d4ab1.png

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

Логичным решением является создание многосторонних договоров, которые позволяют распределить ответственность между участниками CAD/CAM процесса. Здесь появляется огромный выбор различных стратегий выплат, например:

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

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

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

Реализация идеи


Примечание: ниже представлен реальный код, написанный в рамках хакатона.

Проблему описанную выше можно решить с помощью смарт-контрактов: сложные схемы оплат упаковываются в кнопки «accept/decline/pay». Для регулировки всего процесса самым надежным решением будет система с блокчейн-архитектурой.

Так у команды был определенный бэкграунд в разработке и дизайне, для back-end был выбран фреймворк Ruby on Rails (RoR), для front-end — JavaScript-фреймворк AngularJS.

С написанием смарт-контрактов было немного сложнее, так как никто из участников ранее не сталкивался с подобной задачей. Поэтому была выбрана платформа Ethereum (инструмент для создания децентрализованных онлайн-сервисов на базе блокчейна) на основе Azure Blockchain as a Service. Смарт-контракты программировались на специальном языке Solidity.

Участники поделились двумя вопросами, которые возникли у них при работе с данным инструментом, и ответами на них.

Где хранится контракт и кто обеспечивает его корректное исполнение?
Когда смарт-контракт написан и отлажен, он помещается в цепочку блоков транзакций, и может быть проверен (но не изменен!) любым пользователем системы, если тот знает адрес по которому расположен этот смарт-контракт. Корректность самого смарт-контракта зависит от того, насколько корректно его написал программист. Если смарт-контракт был описан неверно, его нельзя исправить и придется поместить другой смарт-контракт по другому адресу.

Какова цена создания смарт-контракта?
Для создания смарт-контракта требуется израсходовать некоторое количество внутренней валюты (Eth), чем выше будет его цена, тем выше он получает приоритет у майнеров (это машины которых вычисляют криптоблоки). Майнеры нужны для того, чтобы смарт-контракт был обработан и добавлен в блокчейн. Если первый взнос будет минимальным, может возникнуть ситуация, в которой смарт-контракт никогда не будет размещен в глобальном блокчейне. Стоит обратить внимание, что также можно задать время жизни контракта.

Что нужно знать для работы с платформой Ethereum для клиентской стороны


Прежде всего, вам необходимо понять для какой платформы вы пишете. Как писали выше, в данном решении был использован фреймворк AngularJS, поэтому вся логика была помещена в контроллер, и там происходила вся работа с web3.js.

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

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

var Web3 = require('web3');
var web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider("http://адрес_сервера:8545"));
var accounts = web3.eth.accounts;

accounts — это все аккаунты, которые задействованы в программе подключения к блокчейну (в нашем случае, это geth).

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

	function getBalance(address){
var funds = web3.eth.getBalance(address);
return funds;
}

Попробуем оплатить что-нибудь через смарт-контракт по адресу contractAddress:
function pay (amount, myToken, password, token, contractAddress){
web3.personal.unlockAccount(myToken,password);
var contract = web3.eth.contract(abi).at(contractAddress);
      	var res = contract.initDoctor.sendTransaction(token, {from:myToken, value:web3.toWei(amount,'ether')});
alert("you dropped to system with token "+token); 
}

Примечание: для простоты был задан пароль в виде plain text, но в реальной системе так делать нельзя.

Это основные функции, которые необходимо знать для вызова смарт-контрактов. Подробности можно узнать на официальном сайте Ethereum.

Что нужно знать для написания смарт-контракта на языке Solidity


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

06c23034a6eb4b649aacab16fcefc913.png

Далее в блокчейне для написания смарт-контракта был использован код:

pragma solidity ^0.4.0;
contract Dental {
    uint cadPrice = 10;
    uint millPrice = 10;
    uint digitizePrice = 10;

	mapping (address => uint) doctor_balances;
	mapping (address => uint) digitizer_balances;
	mapping (address => uint) cad_balances;
	mapping (address => uint) mill_balances;
	mapping (address => uint) statuses; 
	//0 -start,
	//1 - digitizer initialized,
	//2 - cad initialized,
	//3 - mill initialized,
	//4 - digitizer ready,
	//5 - cad_ready,
	//6 - mill ready,
	//7 -payed
    mapping (address => address) digitizer_addresses;
    mapping (address => address) cad_addresses;
    mapping (address => address) mill_addresses;
    
    function initDoctor() {  //Загрузка денег
       doctor_balances[ msg.sender ] += msg.value;
       statuses[msg.sender] = 0;
    }
    function initDigitizer(address digitizerAddr) {
       digitizer_addresses[msg.sender]  = digitizerAddr;
       digitizer_balances[msg.sender]  += msg.value;
       if (statuses[msg.sender] == 0) statuses[msg.sender] = 1;
    }
    function initCad(address cadAddr) {
       cad_addresses[msg.sender]        =  cadAddr;
       doctor_balances[ msg.sender ]    -= cadPrice;
       cad_balances[msg.sender]         += msg.value;
       if (statuses[msg.sender] == 1) statuses[msg.sender] = 1;
    }
    function initMill(address millAddr) {
       mill_addresses[msg.sender]  = millAddr;
       mill_balances[msg.sender]  += msg.value;
       if (statuses[msg.sender] == 2) statuses[msg.sender] = 3;
    }

    function digitizerDone() {
        if (statuses[msg.sender]==3) statuses[msg.sender] = 4;
    }

    function cadDone() {
       if (statuses[msg.sender]==4) statuses[msg.sender] = 5;
    }

    function millDone() {
       if (statuses[msg.sender]==5) statuses[msg.sender] = 6;
    }

    function doctorDone(bool happy) payable returns (bool) {
        if (statuses[msg.sender]!=6) return false;
        if (!happy){
            doctor_balances[msg.sender] += digitizer_balances[msg.sender];
            doctor_balances[msg.sender] += cad_balances[msg.sender];
            doctor_balances[msg.sender] += mill_balances[msg.sender];
            digitizer_balances[msg.sender]  = 0;
            cad_balances[msg.sender]        = 0;
            mill_balances[msg.sender]       = 0;
            return false;
        }
            
        bool digitizerOk = digitizer_addresses[msg.sender].send(digitizer_balances[msg.sender]);
        digitizer_balances[msg.sender] = 0;
        bool cadOk       = cad_addresses[msg.sender].send(cad_balances[msg.sender]);
        cad_balances[msg.sender] = 0;
        bool millOk      = mill_addresses[msg.sender].send(mill_balances[msg.sender]);
        mill_balances[msg.sender] = 0;
        return (digitizerOk && cadOk && millOk);
    }
}

Разберем его подробнее:

1. Сначала указываем версию Solidity и объявляем контракт:

pragma solidity ^0.4.0;
contract Dental {

2. задаем стоимость услуг 3D-сканирования, дизайна и фрезерования:
    uint cadPrice = 10;
    uint millPrice = 10;
    uint digitizePrice = 10;

3. Создаем массивы балансов для оплаты участников процесса:
	mapping (address => uint) doctor_balances;
	mapping (address => uint) digitizer_balances;
	mapping (address => uint) cad_balances;
	mapping (address => uint) mill_balances;

4. Указываем статусы:
	mapping (address => uint) statuses; 
	//0 - start,
	//1 - digitizer initialized,
	//2 - cad initialized,
	//3 - mill initialized,
	//4 - digitizer ready,
	//5 - cad_ready,
	//6 - mill ready,
	//7 -payed

5. Создаем массивы аккаунтов участников процесса (без врачей):
    mapping (address => address) digitizer_addresses;
    mapping (address => address) cad_addresses;
    mapping (address => address) mill_addresses;

6. Инициализируем врача, им будет считаться отправитель. Обратите внимание, что он может брать новые заказы, только если у него указан статус «еще не начал» или «заказ завершен»:
    function initDoctor() {  //Загрузка денег
       if (statuses[msg.sender] == 0 || statuses[msg.sender] == 7){
doctor_balances[ msg.sender ] = msg.value;
statuses[msg.sender] = 0;
        }
    }


7. Инициализируем сканировщика, который будет задействован, если у врача стоит статус «еще не начал»:
    function initDigitizer(address digitizerAddr) {
       digitizer_addresses[msg.sender]  = digitizerAddr;
       digitizer_balances[msg.sender]  = msg.value;
       if (statuses[msg.sender] == 0) statuses[msg.sender] = 1;
    }

8. Аналогично повторяем с дизайном:
    function initCad(address cadAddr) {
       cad_addresses[msg.sender]        =  cadAddr;
       doctor_balances[ msg.sender ]    -= cadPrice;
       cad_balances[msg.sender]         = msg.value;
       if (statuses[msg.sender] == 1) statuses[msg.sender] = 1;
    }

9. Аналогично повторяем с фрезеровщиком:
    function initMill(address millAddr) {
       mill_addresses[msg.sender]  = millAddr;
       mill_balances[msg.sender]  += msg.value;
       if (statuses[msg.sender] == 2) statuses[msg.sender] = 3;
    }


10. Далее подтверждаем работу сканировщика:
    function digitizerDone() {
        if (statuses[msg.sender]==3) statuses[msg.sender] = 4;
    }

11. Подтверждаем работу дизайнера:
    function cadDone() {
       if (statuses[msg.sender]==4) statuses[msg.sender] = 5;
    }

12. Подтверждаем работу фрезеровщика:
    function millDone() {
       if (statuses[msg.sender]==5) statuses[msg.sender] = 6;
    }

13. Врач может принять или не принять работу. В последнем случае все деньги будут возвращены на его счет.). Если работа еще не отфрезерована, то ничего не происходит. Если врач принимает работу, деньги отправляются на счета участников:
    function doctorDone(bool happy) payable returns (bool) {
        if (!happy){
            doctor_balances[msg.sender] += digitizer_balances[msg.sender];
            doctor_balances[msg.sender] += cad_balances[msg.sender];
            doctor_balances[msg.sender] += mill_balances[msg.sender];
            digitizer_balances[msg.sender]  = 0;
            cad_balances[msg.sender]        = 0;
            mill_balances[msg.sender]       = 0;
            return true;
        }
       if (statuses[msg.sender]!=6) return false;   
        bool digitizerOk = digitizer_addresses[msg.sender].send(digitizer_balances[msg.sender]);
        digitizer_balances[msg.sender] = 0;
        bool cadOk       = cad_addresses[msg.sender].send(cad_balances[msg.sender]);
        cad_balances[msg.sender] = 0;
        bool millOk      = mill_addresses[msg.sender].send(mill_balances[msg.sender]);
        mill_balances[msg.sender] = 0;
        if (digitizerOk && cadOk && millOk) statuses[msg.sender]=7;
        return (digitizerOk && cadOk && millOk);
    }
}

Слово команде проекта Digital Dentistry Exchange


Мы спросили участников проекта, какое будущее они видят у технологии блокчейн:

«Технология блокчейн — потенциально самая подходящая технология для проведения транзакций любых типов, начиная от финансовых услуг заканчивая приготовлением еды. Единственным дополнением к блокчейну должен быть доработанный механизм proof-of-work, который будет приносить пользу людям или науке (например, давняя задача поиска целых значений параметров a, b, c в выражении a^3+b^3+c^3=33).

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

Количество возможных приложений может быть огромным — главное тестировать идеи, реализации и активно их внедрять. Также было бы не лишним внедрение правового регулирования и ISO стандарта систем с архитектурой блокчейн.»

На фотографии ниже авторы материала: Константин Скобельцын, Виталий Дементьев, Ринат Хатипов, Айдар Нигматжанов, Роман Варнава.
e97c21f688d74ed4bd74345deaa2008e.jpg

Комментарии (1)

  • 19 октября 2016 в 21:33

    0

    Класс!

© Habrahabr.ru