Хабрахабр

[Из песочницы] Как самостоятельно имплементировать (Proof of Existence) за 2 шага

Всем привет! Я работаю в компании, QuantNet, которая проводит конкурсы алгоритмических стратегий. В недавнем времени передо мной встала важная задача — обеспечить гарантии неприкосновенности даты юзеров (это чрезвычайно важно, так как для корректной проверки эффективностей стратегий необходимо использовать данные мировых финансовых рынков в режиме реального времени).

В интернете об этом написано достаточно, но специфика платформы заставила меня немного поломать голову. Вот тут-то я и столкнулся с концепцией PoE (Proof of Existence). Думаю, особенно актуально это будет для ребят из финтеха. Поэтому я и решил написать эту статью и поделиться своим опытом в архитектуре и имплементации PoE.

Свою статью я разделил на 3 основных блока:

  • Что такое PoE и когда это может понадобиться
  • Алгоритм имплементации
  • Решение моего конкретного кейса

Итак, что такое Proof of Existence?

Proof of Existence (дословно, доказательство существования) помогает доказать, что документ, файл или данные были созданы в определенную дату и время. Самый масштабный вариант применения — это регистрация патента. Но из того, что я видел, чаще всего это применяется в областях на стыке финансов и IT.

Вы решаете продавать ваши прогнозы другим игрокам рынка. Пример из моей сферы алготрейдинга: у вас есть алгоритм, который дает около 70% верных прогнозов по акциям на следующие 2 недели. гарантировать их реализацию в конкретное время. Дело за малым — убедить покупателя, что ваши прогнозы верны и были сделаны до результатов торгов, т.е.

Правильно, имплементировать PoE. Как это можно гарантировать?

Алгоритм имплементации PoE

Для начала нужно:

  1. Подготовить файл, который вы хотите запатентовать. (Я делал PDF, но вы можете использовать любой другой контейнер).
  2. Получить хеш данного файла (Я использовал формат sha256).

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

С вводной частью закончили. Все. Теперь переходим к самому интересному.

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

Давайте более детально посмотрим как работает демо.

Предлагаю разделить реализацию на 2 части:

  1. Подготовка смарт контракта и кошелька эфира.
  2. Генерация транзакции в коде на Node.js и закрытого ключа.

Давайте по порядку:

Часть 1: Подготовка смарт контракта и кошелька Etherium

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

Кроме этого, неплохо бы позаботится о том, что только владелец контракта смог добавить новые хеши. Я выбрал простой смарт контракт, который может принимать хеш и с соответствующую датой, формате хеш => дата, также было бы супер иметь метод, который возвращает дату хеша при вызове.

Код смарт-контракта:

```
pragma solidity 0.5.9; /** * @title Ownable * @dev The Ownable contract has an owner address, and provides basic authorization control * functions, this simplifies the implementation of "user permissions". */
contract Ownable /** * @return the address of the owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner()); _; } /** * @return true if `msg.sender` is the owner of the contract. */ function isOwner() public view returns (bool) { return msg.sender == _owner; } /** * @dev Allows the current owner to transfer control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0)); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; }
} /** * @title HashStore * @dev The contract store the hashes and returns date by hash * Only the owner can add new hashes */
contract HashStore is Ownable { mapping(bytes32 => uint256) private _hashes; event HashAdded(bytes32 hash); function addHash(bytes32 rootHash) external onlyOwner { require(_hashes[rootHash] == 0, "addHash: this hash was already deployed"); _hashes[rootHash] = block.timestamp; emit HashAdded(rootHash); } function getHashTimestamp(bytes32 rootHash) external view returns (uint256) { return _hashes[rootHash]; }
} ```

Как вы уже заметили, мы использовали 2 отдельных контракта: Ownable и HashStore.
Контракт HashStore отвечает за хранение хешей и выдачи даты хеша по запросу. Контракт Ownable отвечает за проверку того, что новый хеш был добавлен исключительно владелецем контракта.

Если хеши внутри контракта совпадут, транзакция будет отклонена. Чтобы добавить хэш нужно вызвать метод addHash, передав значение sha256 как аргумент нашего файла. Проверяется это тут: Так фильтруется нежелательное дублирование значений с разными датами.

require(_hashes[rootHash] == 0, "addHash: this hash was already deployed");

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

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

  1. адрес эфира для взаимодействия с блокчейном
  2. некоторое количсетво эфира для вызова методов и развертывание контрактов.

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

Часть 2: Генерация транзакции в Node.js и закрытого ключа

Осталось настроить взаимодействие с блокчейном. Итак, к этому моменту у нас уже есть кошелек эфира, его секретный ключ, контракт в тестовой сети и хеш данных.

Свой я создавал с помощью сервиса infura.io и выглядит он примерно так: Для этого будем использовать библиотеку web3.js и создадим токен для своей ноды.

ropsten.infura.io/v3/YOUR_TOKEN_HERE

Для хеширования используем пакет sha256. Формат данных может быть любым, но в примере мы используем данные в JSON.

Как я решил свой кейс с помощью PoE?

Кроме самого наличия PoE, для меня было важно не перегружать пользователей работой с блокчейном и платой комиссии за транзакцию.Например, вызов метода addHash(bytes32 rootHash) стоит 0.2 finney (0.0002 ETH или $0.06 по курсу июнь 2019).

1. В день выходило около 30 выводов позиции стратегий, т.е это стоит нам $2. Если количество пользователей увеличится в 100 раз, а курс Эфира пойдет вверх, стоимость, естественно, пойдет в верх.

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

Мы не видим проблем с масштабируемостью, однако, всегда можно разделить вывод позиции стратегий на несколько блоков и сохранить в сеть блокчейн несколько хешей. Получаем решение, которое не уступает по функциональности, однако, значительно дешевле. А участник легко сможет верифицировать отдельный хэш с помощью других соседних хешей.

В итоге

Для верификации мы создали специальный шаблон, который доступен в виде Jupyter notebook… В любой момент пользователь может загрузить шаблон, заново сгенерировать все и проверить, что все позиции действительно те, которые были созданы и созранены в прошлом.

```
Как это работает:
1. Шаблон загружает с API вывод стратегий пользователя на конкретную дату
1. Шаблон хеширует этот вывод
2. Шаблон загружает с API идентификатор вывода, идентификаторы и хеши других выводов на нужную дату
3. Шаблон хеширует все вместе и проверяет этот хеш с хешем, который доступен в блокчейне на нужную дату
Если хеши совпали значит все работает корректно. Таким же образам шаблон автоматически проверяет все даты и выводы.<source lang="coffeescript"> ```

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»