---
tags: onti, fintech, assignments, ethereum, msfaceapi
---
Описание учебно-тренировочных сборов профиля ФТ ОНТИ 2018/19
====
Учебно-тренировочные сборы (УТС) проводятся для того, чтобы помочь участникам финала профиля подготовиться к решению финальной задачи. Важно проводить (и участвовать в) УТС, поскольку не всегда формат или система проверки решения задач второго этапа олимпиады позволяют в полной мере сподвигнуть школьников к изучению определенных тем или приобретению определенных навыков, требуемых в финале.
Сформулированные ниже задачи могут также использоваться вне подготовки к финалу олимпиады (например, в рамках хакатонов, занятий в проектных школах или тематических кружках) для практического знакомства школьников с программированием приложений для блокчейн сетей или для понимания основ функционирования систем идентификации человека по лицу.
## План учебно-тренировочных сборов
### Этап первый
Используются общедоступные материалы - ноутбук с установленным ПО для написания программ на языке Python, с python-библиотекой [web3.py](https://web3py.readthedocs.io/en/stable/), клиент системы ведения версий Git. Хакатон дает навыки в написании и отладке приложения, управляющим балансом пользователя, для блокчейн сети, основанной на виртуальной машине Ethereum.
### Этап второй
Используются общедоступные материалы - ноутбук с установленным ПО для написания программ на языке Python, с python-библиотекой [web3.py](https://web3py.readthedocs.io/en/stable/), с ПО для написания программ на языке [Solidity](https://solidity.readthedocs.io), интернет-браузер Chrome с установленным расширением [NiftyWallet](https://chrome.google.com/webstore/detail/nifty-wallet/jbdaocneiiinmjbjlgalhcelgbejmnid), клиент системы ведения версий Git. Хакатон знакомит участников с принципами создания и отладки децентрализованных приложений взаимодействующих со смарт-контрактами для блокчейн сети, основанной на виртуальной машине Ethereum.
### Этап третий
Используются общедоступные материалы - ноутбук c камерой и с установленным ПО для написания программ на языке Python, с python-библиотекой [cognitive_face](https://github.com/Microsoft/Cognitive-Face-Python), клиент системы ведения версий Git. Также для каждого участника учебно-тренировочных сборов необходима регистрация на сервисе Microsoft Azure, а именно необходима [подписка на Cognitive Services](https://docs.microsoft.com/en-us/azure/cognitive-services/cognitive-services-apis-create-account). Учебно-тренировочные сборы знакомят участников с принципами создания и отладки приложений для идентификации человека по лицу с использованием [Microsoft Face API](https://azure.microsoft.com/en-us/services/cognitive-services/face/).
## Детальный план первого этапа
### Входные требования к участникам первого этапа
Знание базовых алгоритмических конструкций языка и структур хранения данных языка программирования Python.
Понимание криптографических основ функционирования блокечейн сети, основанной на виртуальной машине Ethereum, и базовых основ хранения информации о балансах пользователей.
Умение использовать системы ведения версий Git для разработки программного обеспечения.
### Теоретические знания, получаемые на сборах
Понимание принципов взаимодействия с узлом Ethereum через JSON-RPC, понимание функционала доступного API и предоставляемого python-библиотекой [web3.py](https://web3py.readthedocs.io/en/stable/) для получения данных из блокчейн, создания транзакций.
### Навыки, получаемые на сборах
Навык создания и отладки Python приложений, через JSON-RPC запросы взаимодействующих с блокчейн сетью, основанной на виртуальной машине Ethereum.
Умение выполнять базовые операции с узлом Ethereum:
* получение баланса
* создание транзакции на изменение баланса
* получение выписки транзакции
### Оборудование
Ноутбук с установленным ПО для написания программ на языке Python, с python-библиотекой [web3.py](https://web3py.readthedocs.io/en/stable/), клиент системы ведения версий Git.
### Формат участия
Индивидуальный. Каждый участник самостоятельно решает задачу на своем комплекте оборудования.
### Требования к проводящему
Необходим человек, который имеет опыт программирования приложений, использующих JSON-RPC запросы, для блокчейн сети на базе виртуальной машины Ethereum, а также навыки написания программ с использованием python-библиотеки `web3.py`.
Рекомендация - иметь несколько ассистентов для помощи основному ведущему учебно-тренировочных сборов. Общее количество проводящих должно исчисляться по 1 человеку на каждые 8 участников.
### Почасовой план
Учебно-тренировочные сборы расчитаны на 4-5 часов.
| Время | Описание |
| :---: | :--- |
| 30 минут | Знакомство с тестовой сетью POA Sokol. Получение тестовых монет на [faucet](https://faucet-sokol.herokuapp.com/). Знакомство с [эксплорером блоков](https://blockscout.com/poa/sokol/). |
| 15 минут | Краткий обзор [JSON-RPC запросов](https://wiki.parity.io/JSONRPC-eth-module), которые могут быть сделаны к узлу Ethereum |
| 15 минут | Краткий обзор API, предоставляемого python-библиотекой [web3.py](https://web3py.readthedocs.io/en/stable/) и необходимого для решения задачи учебно-тренировочных сборов |
| 15 минут | Рассмотрение примеров программ для отправки JSON-RPC запросов к тестовой сети POA Sokol через библиотеку `web3.py`. |
| 15 минут | Постановка задачи. Описание ожидаемых входных и требуемых выходных данных. Предоставление требований к публикации кода на сервере ведения версий git. |
| 3.5 часа | Решение задачи участниками учебно-тренировочных сборов. Приемка работ |
### Описание задачи
Базовая операция, которая может быть выполнена практически на каждом Ethereum узле, - получить баланс на счете пользователя или переслать часть средств на другой счет. Эта минимальная функциональность выполняется той частью программного обеспечения узла, которая называется криптовалютным кошельком.
Ваша задача - автоматизировать перечисленные выше функции.
Вам необходимо разработать приложение (python-скрипт), которое бы принимало параметры через командную строку и в зависимости от параметров выполняло следующие функции:
* вывод баланса счета;
* отправка заданного количества _POA монет_ на другой счет.
Имя исполняемого скрипта должно быть `qadwallet.py`
Скрипт должен выполнять действия, оперируя приватным ключом Ethereum аккаунта. Приватный ключ указывается в шестнадцатиричном формате.
#### Примеры использования
##### Вывод баланса
Первый пример (_US-01_) использования скрипта:
```shell
$ qadwallet.py --key c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
```
Ответом должна быть строка:
```
Balance on "9cce34F7aB185c7ABA1b7C8140d620B4BDA941d6" is 2.5 poa
```
##### Отправка poa монет
Для того, чтобы отправить часть _poa монет_ принадлежащих счету, ассоциированному с приватным ключем, нужно указать адрес получателя и сумму. Адрес отправителя должен быть указан в шестнадцатиричном формате. Сумма для отправки - целое число, измеряется в _Wei_.
Скрипт должен предусматривать, как отправку средств со счета, с которого еще ни разу не было совершено ни одной транзакции, так и со счетов, активно выполнявших переводы.
Второй пример (_US-02_) использования скрипта:
```shell
$ qadwallet.py --key c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 --to EAee08c91B13d8d7A82850b714C7c68826E9CFAe --value 500000000000000000
```
Ответ должен быть следующим:
```
Payment of 500 finney to "EAee08c91B13d8d7A82850b714C7c68826E9CFAe" scheduled
Transaction Hash: 0x27c9181caeb55d37e1105fa1a8648db7fe50f79064b98e56b8e854e3abb43728
```
Еще один пример (_US-03_), демонстрирующий автоматическое масштабирование суммы:
```shell
$ qadwallet.py --key c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 --to EAee08c91B13d8d7A82850b714C7c68826E9CFAe --value 2500000000000000000
Payment of 2.5 poa to "EAee08c91B13d8d7A82850b714C7c68826E9CFAe" scheduled
Transaction Hash: 0x27d6236b24f3643fb6f55442572f0a382bc6fc3674ef64a62f706591235f0ecf
```
Масштабирование суммы - нормализация к одному из возможных значений: _poa_, _finney_, _szabo_, _gwei_, _mwei_, _kwei_, _wei_. Происходит следующим образом:
* Используется минимально возможное нормализованное значение, чья целая часть больше ноля;
* Дробная часть записывается с округлением до $10^{-6}$;
* Завершающие нули в дробной части, полученные полсе округления, не записываются (например, 1.3, но не 1.300000).
Скрипт должен оповещать пользователя, если на счету недостаточно средств для перечисления (_US-04_):
```shell
$ qadwallet.py --key c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 --to EAee08c91B13d8d7A82850b714C7c68826E9CFAe --value 250000000000000000000
No enough funds for payment
```
Четверты пример (_US-05_) демонстрирует возможность получать статус транзакции, в рамках которой осуществлялся перевод:
```shell
$ qadwallet.py --tx 0x27c9181caeb55d37e1105fa1a8648db7fe50f79064b98e56b8e854e3abb43728
```
Ответом должна быть строка:
```
Payment of 500 finney to "EAee08c91B13d8d7A82850b714C7c68826E9CFAe" confirmed
```
Или, в случае, когда транзакция все еще не подтверждена (_US-06_):
```shell
$ qadwallet.py --tx 0x27d6236b24f3643fb6f55442572f0a382bc6fc3674ef64a62f706591235f0ecf
Delay in payment of 2.5 poa to "EAee08c91B13d8d7A82850b714C7c68826E9CFAe"
```
Попытки получить информацию о несуществующей транзакции также должны правильно обрабатываться (_US-07_):
```shell
$ qadwallet.py --tx 0x27d6236b24f3643fb6f55442572f0a382bc6fc3674ef64a62f706591235ffce0
No such transaction in the chain
```
#### Примечание
Скрипт должен работать с Ethereum узлом исключительно через подключение по RPC. В качестве RPC URL должен быть использован `https://sokol.poa.network`.
### Проверка решения
Существует способ автоматической проверки правильности решения задачи. Для этого необходимо [создать новый проект на сервере GitLab](https://gitlab.com/projects/new). При создании проекта необходимо использовать специальный шаблон, который и позволит выполнять автоматическую проверку.
* [Инструкция по созданию проекта из шаблона](https://hackmd.io/@koal/r1rM9FAvS)
* [Шаблон проекта для задачи "Quick and Dirty wallet"](https://drive.google.com/file/d/1EeLQ-h5HF2kXwHBzrjg9PB6sfr8J6Bx3/view?usp=sharing)
Сразу после создания проекта проверка автоматически запуститься. При этом будет сообщение об ошибках. Это нормально. Во-первых, создался только проект, а не решение. Во-вторых, аккаунт, использующийся для автоматического тестирования решения, может не иметь достаточно средств. В разделе _"Проверка решения"_ в файле `README.md` проекта описано, что нужно сделать для пополнения счета этого аккаунта.
После создания шаблона нужно склонировать репозиторий на локальную машину.
Каждый раз, когда будете делать `push` в данный репозиторий будет автоматически проводиться предварительная проверка решения. Результат проверки можно будет видеть в GitLab в разделе `CI/CI -> Pipelines`.
## Детальный план второго этапа
### Входные требования к участникам второго этапа
Знание базовых алгоритмических конструкций языка и структур хранения данных языка программирования Python.
Умение создавать и отлаживать Python приложения, взаимодействующих с блокчейн сетью, основанной на виртуальной машине Ethereum, посредством python-библиотеки [web3.py](https://web3py.readthedocs.io/en/stable/).
Умение создавать аккаунт в блокчейн сети на базе виртуальной машины Ethereum, создавать транзакции для изменения баланса.
Базовый уровень знания языка [Solidity](https://solidity.readthedocs.io): синтаксис, операции управления ходом программы, доступные структуры данных и их свойства, понимание основ взаимодействия смарт-контрактов Ethereum c данными в блокчейн.
Умение использовать системы ведения версий Git для разработки программного обеспечения.
### Теоретические знания, получаемые на сборах
Базовое понимание процесса развертывания контрактов в блокчейн сети на базе виртуальной машины Ethereum.
Знание методов получения информации из базы данных, представленной блокчейн сетью: входные данные транзакции, данные контракта, результаты исполнения кода контракта.
Знание методов изменения информации в базе данных, представленной блокчейн сетью, посредством вызова на исполнение кода контракта.
Понимание интеграционного тестирования и возможных способов его автоматизации.
### Навыки, получаемые на сборах
Навык создания и отладки простых контрактов на языке Solidity в [IDE Remix](http://remix.ethereum.org).
Умение создавать приложения на языке Python для развертывания контракта в блокчейн сети базе виртуальной машины Ethereum.
Умение использовать библиотеку `web3.py` для создания транзакций для вызова на исполнение кода контракта, для нетранзакционного вызова кода контракта, для доступа к данным, генерируемых контрактом, в выписке транзакции.
Навыки организации интеграционного тестирования продукта, автоматизации процессов объединения нескольких компонент программного обеспечения перед проведением тестирования.
Навыки командной работы в рамках одного проекта ИТ-направленности.
### Оборудование
Ноутбук с установленным ПО для написания программ на языке Python, с python-библиотекой [web3.py](https://web3py.readthedocs.io/en/stable/), с ПО для написания программ на языке [Solidity](https://solidity.readthedocs.io), интернет-браузер Chrome с установленным расширением [NiftyWallet](https://chrome.google.com/webstore/detail/nifty-wallet/jbdaocneiiinmjbjlgalhcelgbejmnid), клиент системы ведения версий Git.
### Формат участия
Командный (2-3 человека в команде). Каждая команда решает задачи на своем комплекте оборудования.
Рекомендуемые роли:
* Python-разработчик (разработка и отладка кода на python)
* Solidity-разработчик (разработка контракта на solidity)
* DevOps-инженер (настройка окружения для тестирования с загрузкой артефактов из репозиториев git, настройка автоматической регистрации новых версий контрактов, проведение (и возможная автоматизация) интеграционного тестирования, коммуникация с разработчиками об выявленных ошибках, отслеживание статуса их исправления)
### Требования к проводящему
Необходим человек, который имеет опыт разработки контрактов для блокчейн Ethereum на языке Solidity. Также требуется опыт написания python-приложений для взаимодействия с контрактами посредством библиотеки `web3.py`.
Рекомендация - иметь несколько ассистентов для помощи основному ведущему учебно-тренировочных сборов. Общее количество проводящих должно исчисляться по 1 человеку на каждые 8 участников.
### Почасовой план
Учебно-тренировочные сборы расчитаны на 4-5 часов.
| Время | Описание |
| :---: | :--- |
| 30 минут | Знакомство со средой разработки [IDE Remix](http://remix.ethereum.org). |
| 15 минут | Рассмотрение примеров работы с данными в базе данных, представленной блокчейн: транзакционное изменение базы данных, нетранзакционный вызов кода контракта, данные, генерируемые контрактом и хранимые в выписке траназкции. |
| 30 минут | Краткий обзор API, предоставляемого python-библиотекой [web3.py](https://web3py.readthedocs.io/en/stable/): развертывание контракта, вызов методов контракта, получение информации из выписки транзакции. |
| 15 минут | Рассмотрение процесса использования кошелька [NiftyWallet](https://chrome.google.com/webstore/detail/nifty-wallet/jbdaocneiiinmjbjlgalhcelgbejmnid) для деплоймента контракта в тестовую сеть Sokol, верификация контракта, работа с данными контракта |
| 15 минут | Постановка задачи. Описание ожидаемых входных и требуемых выходных данных. Предоставление требований к публикации кода на сервере ведения версий git. |
| 3 часа | Решение задачи участниками учебно-тренировочных сборов. Приемка работ |
### Описание задачи
Контракты в сети блокчейн могут использоваться для разных нужд - автоматически исполнять заранее заданные договоренности при достижении каких-то условий или возникнования событий, описывать ценности реального мира и взаимодействие с ними, проводить голосования, предоставлять доступ к структурированной информации, отличающейся от информации об изменении балансов.
То, что код контракта, помещенный в блокчейн, не может изменяться (если это заранее не обговорено в самом контракте) позволяет гарантировать, что даже через несколько месяцев никто не сможет изменить его поведение после того, как пользователь ознакомился с контрактом. Это как раз и позволяет гарантировать исполнение заранее заданных договоренностей.
Ваща задача - написать децентрализованное приложение, частью которого является контракт, отвечающий за хранение соответствий имен пользователей и аккаунтов блокчейн сети. Такой контракт может быть часть KYC (Know Your Customer) систем, которые требуются от криптовалютных бирж и обменников, чтобы не нарушать законадальство.
Контракт будет обладать следующей функциональностью::
* добавление нового соответствия между именем пользователя и его аккаунтом;
* удаление соответствия между именем пользователя и его аккаунтом;
* получение аккаунта по имени пользователя;
* получение имени пользователя по аккаунту.
#### Интерфейсы контракта
Ниже приводятся методы, доступ к которым контракт должен предоставлять, и описание логики их работы.
1. Регистрация соответствия имени и аккаунта
```solidity
function registerName(string _name);
```
Данный метод позволяет зарегистрировать имя для аккаунта, выполняющего вызов этого метод
а
*
Если имя уже зарегистрировано для данного аккаунта, транзакция, в рамках которой вызвается метода, откатывается.
* Имя не должно быть пустой строкой.
* Допускается регистрировать одно имя для разных аккаунтов.
* Если имя регистрируется успешно, то испускается следующее событие (`event`):
```solidity
event NameRegistered(address _address, string _name);
```
* Метод не должен потреблять больше `75000` газа (допускается привышение этого лимита если метод вызывается для регистрации шестого и последующих соответствий под данным именем зарегистрировано к моменту вызова метода не более четырех аккаунтов)
2. Удаление соответствия имени и аккаунта
```solidity
function unregisterName();
```
Данный метод позволяет удалить соответствие между именем и аккаунтом.
* Удаляется соответствие для аккаунта, вызывающего метод.
* Если для данного аккаунта нет зарегистрированного соответствия, транзакция, в рамках которой вызвается метода, откатывается.
* Если соответствие успешно удалено, то испускается следующее событие (`event`):
```solidity
event NameUnregistered(address _address);
```
* Транзакция, в ходе которой вызывается метод не должна потреблять больше `21000` газа для случая, когда для имени, с котороым удаляется соответствие, зарегистрировано 5 и меньше аккаунтов.
3. Получить имя соответствующее аккаунту
```solidity
function getName(address _address) returns (string _name)
```
Метод принимает в качестве входных данных адрес аккаунта и возвращает имя, соответствующее этому адресу.
* Если с адресом аккаунта никогда не ассоциировалось имя, метод возвращает пустую строку.
* Если соответствие имени и данного аккаунта было удалено, метод возвращает пустую строку.
4. Получить адреса соответствующих имени
```solidity
function getAddresses(string _name) returns (address [] _address);
```
Метод позволяет получить массив всех адресов, соответствующих указанному имени.
* Если соответствие с именем еще никем не регистрировалось, метод возвращает пустой массив.
* Если имя соответствует только одному аккаунту, то возвращается массив только с одним адресом.
* Если для имени было удалено соответствие с аккаунтом, то адрес этого аккаунта не должен присутсвовать в возвращаемом массиве.
Контракт должен быть написан на языке Solidity и код должен быть совместим с версией компилятора `solc` `0.5.4`. При проверке контракта будет использован флаг, включающий оптимизацию.
Файл, содержащий контракт, должен называться `registrar.sol`. Контракт, который будет тестироваться, должен называться `Registrar`.
#### Клиентская часть
Также необходимо разработать приложение (python-скрипт), которое бы принимало параметры через командную строку, позволяло регистрировать контракт в блокчейн сети и, в зависимости от параметров, вызывало тот или иной интерфейс контракта.
Имя исполняемого скрипта должно быть `registrar.py`
Скрипт должен выполнять действия, включая регистрацию контракта, оперируя приватным ключом Ethereum аккаунта. Приватный ключ указывается в файле `account.json` в шестнадцатиричном формате:
```json
{"account": "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"}
```
Скрипт должен работать с Ethereum узлом исключительно через подключение по RPC.
Цена газа во всех транзакциях должна браться из оракула (поставщик данных из реального мира), возвращающего данные о цене в виде:
```json
{"block_time":19.91,"fast":14.4,"instant":25.0,"block_number":7240426,"standard":5.0,"health":true,"slow":3.0}
```
При выборе должна использоваться цена из значения `fast`, измеряемая в `Gwei`. Оракул доступен по HTTP протоколу. Пример оракула: https://gasprice.poa.network.
Ссылки на RPC узел и оракула цены газа передаются через конфигурационный файл `network.json`. Он содержит следующую информацию:
* `rpcUrl` - URL для доступа к узлу по JSON RPC;
* `gasPriceUrl` - URL для доступа к сервису, предоставляющему цену за газ.
Пример файла:
```json
{"rpcUrl": "https://sokol.poa.network", "gasPriceUrl": "https://gasprice.poa.network/"}
```
#### Примеры использования
##### Регистрация контракта (US-01)
Пользователь может зарегистрировать контракт в блокчейн, чтобы в дальнейшем пользователи сервиса обращались к данному контракту по его адресу.
```shell
$ registrar.py --deploy
Contract address: 0xc78282BF9b270e632309bc6901D3F46416E12c5A
```
После регистрации контракта в директории, из которой запускается скрипт `registrar.py` должен создаться файл `database.json` с адресом контракта и номером блока, в котором данный контракт был зарегистрирован:
```shell
$ cat database.json
{"registrar": "0xc78282BF9b270e632309bc6901D3F46416E12c5A",
"startBlock": 123456}
```
Последующий вызов `registrar.py --deploy` регистрирует новый контракт вне зависимости от того, есть в текущей директории файл `database.json`.
##### Цена газа для транзакции регистрации контракта (US-02)
Для проведения транзакции выбирается цена из значения `fast`, возвращенного сервисом `https://gasprice.poa.network`.
Сразу после регистрации контракта значение из `fast` умноженное на 1000000000 из вывода команды
```shell
$ curl -X GET "https://gasprice.poa.network" -H "accept: application/json"
```
и значение `gasPrice` из самой первой транзакции в списке из вывода следующей команды:
```shell
$ curl -X GET "https://blockscout.com/poa/sokol/api?module=account&action=txlist&address=<ACCOUNT>&sort=desc" -H "accept: application/json"
```
должны совпадать.
##### Регистрация имени пользователя (US-03)
Пользователь может добавить в контракт соответствие имени своему аккаунту.
```shell
$ registrar.py --add "Elon Musk"
Successfully added by 0x27d6236b24f3643fb6f55442572f0a382bc6fc3674ef64a62f706591235f0ecf
```
Адрес контракта для регистрации пользователя берется из файла `database.json`.
##### Запрет нескольких регистраций с одного аккаунта (US-04)
Пользователь не может добавить в контракт соответствие еще одного имени своему аккаунту.
```shell
$ registrar.py --add "Mark Zuckerberg"
One account must correspond one name
```
В сети блокчейн не создается траназакций с данного аккаунта.
##### Обработка ошибок при регистрации имени пользователя (US-05)
Если на счету пользователя недостаточно средств для проведения транзакции, то выводится соответствующее сообщение:
```shell
$ registrar.py --add "Vitalik Buterin"
No enough funds to add name
```
##### Цена газа для траназкции на регистрации имени пользователя (US-06)
Для проведения транзакции выбирается цена из значения `fast`, возвращенного сервисом `https://gasprice.poa.network`.
Сразу после добавления имени пользователя в контракт значение из `fast` умноженное на 1000000000 из вывода команды
```shell
$ curl -X GET "https://gasprice.poa.network" -H "accept: application/json"
```
и значение `gasPrice` из самой первой транзакции в списке из вывода следующей команды:
```shell
$ curl -X GET "https://blockscout.com/poa/sokol/api?module=account&action=txlist&address=<ACCOUNT>&sort=desc" -H "accept: application/json"
```
должны совпадать.
##### Удаление имени пользователя (US-07)
Пользователь может удалить из контракта соответствие имени своему аккаунту.
```shell
$ registrar.py --del
Successfully deleted by 0x5442572f0a382bc6fc3674ef64a62f706591235f0ecf27d6236b24f3643fb6f5
```
Адрес контракта для удаления пользователя берется из файла `database.json`.
##### Удаление несуществующего соответствия (US-08)
Если в контракте нет соответствия имени пользователя и аккаунта, то выводится соответствующее сообщение.
```shell
$ registrar.py --del
No name found for your account
```
##### Обработка ошибок при удалении имени пользователя (US-09)
Если на счету пользователя недостаточно средств для проведения транзакции, то выводится соответствующее сообщение:
```shell
$ registrar.py --del
No enough funds to delete name
```
##### Цена газа для траназкции на удаление имени пользователя (US-10)
Для проведения транзакции выбирается цена из значения `fast`, возвращенного сервисом `https://gasprice.poa.network`.
Сразу после удаления имени пользователя в контракт значение из `fast` умноженное на 1000000000 из вывода команды
```shell
$ curl -X GET "https://gasprice.poa.network" -H "accept: application/json"
```
и значение `gasPrice` из самой первой транзакции в списке из вывода следующей команды:
```shell
$ curl -X GET "https://blockscout.com/poa/sokol/api?module=account&action=txlist&address=<ACCOUNT>&sort=desc" -H "accept: application/json"
```
должны совпадать.
##### Получение аккаунта по имени пользователя (US-11)
Любой пользователь может получить аккаунт по имени пользователя
```shell
$ registrar.py --getacc "Elon Musk"
Registered account is 0x9cce34f7ab185c7aba1b7c8140d620b4bda941d6.
```
Транзакция в блокчейн не отправляется.
##### Обработка ошибок при получении аккаунта по имени пользователя (US-12)
Если имя пользователя не было зарегистрировано, выдается соответствующая сообщение.
```shell
$ registrar.py --getacc "Vitalik Buterin"
No account registered for this name
```
Транзакция в блокчейн не отправляется.
##### Получение аккаунта для удаленного соответствия (US-13)
Если пользователь удалил соответствие имени и аккаунта, выдается такое же сообщение как и в том случае, когда соответствие не было зарегистрировано вообще.
```shell
$ registrar.py --add "Mark Zuckerberg"
Successfully added by 0xdc367624ef64a62f72706591235f0eb6f554425cf2724f3636b43ff0a382bc6f
$ registrar.py --del
Successfully deleted by 0xecf27d6236b24f3643fb6f55442572f0a382bc6fc3674ef64a62f706591235f0
$ registrar.py --getacc "Mark Zuckerberg"
No account registered for this name
```
##### Получение имени пользователя по аккаунту (US-14)
Любой пользователь может получить имя пользователя по аккаунту
```shell
$ registrar.py --getname 0x9cce34f7ab185c7aba1b7c8140d620b4bda941d6
Registered account is "Elon Musk"
```
Транзакция в блокчейн не отправляется.
##### Обработка ошибок при получении имени пользователя по аккаунту (US-15)
Если имя пользователя не было зарегистрировано, выдается соответствующая сообщение.
```shell
$ registrar.py --getname 0xca35b7d915458ef540ade6068dfe2f44e8fa733c
No name registered for this account
```
Транзакция в блокчейн не отправляется.
##### Получение аккаунта для удаленного соответствия (US-16)
Если пользователь удалил соответствие имени и аккаунта, выдается такое же сообщение как и в том случае, когда соответствие не было зарегистрировано вообще.
```shell
$ registrar.py --add "Mark Zuckerberg"
Successfully added by 0xdc367624ef64a62f72706591235f0eb6f554425cf2724f3636b43ff0a382bc6f
$ registrar.py --del
Successfully deleted by 0xecf27d6236b24f3643fb6f55442572f0a382bc6fc3674ef64a62f706591235f0
$ registrar.py --getname 0x14723a09acff6d2a60dcdf7aa4aff308fddc160c
No account registered for this name
```
##### Получение списка всех соответствий (US-17)
Пользователь может получить все зарегистрированные соответствия
```shell
$ registrar.py --add "Vitalik Buterin"
Successfully added by 0x62f72706591235f0eb6f554425cf2724f36dc367624ef64a36b43ff0a382bc6f
$ registrar.py --del
Successfully deleted by 0xe0a382bc6fc3674ef64a62f706591235f0cf27d6236b24f3643fb6f55442572f
$ registrar.py --list
"Elon Musk": 0x9cce34f7ab185c7aba1b7c8140d620b4bda941d6
"Mark Zuckerberg": 0xdd870fa1b7c4700f2bd7f44238821c26f7392148
```
Транзакция в блокчейн не отправляется.
##### Получение нескольких аккаунтов по одному имени пользователя (US-18)
Любой пользователь получит несколько аккаунтов, если зарегистрировано несколько пользователей под этим именем
```shell
$ registrar.py --getacc "Elon Musk"
Registered accounts are:
0x9cce34f7ab185c7aba1b7c8140d620b4bda941d6
0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db
```
Транзакция в блокчейн не отправляется.
##### Оптимизация контракта (US-19)
Если пользователь удалил соответствие имени и аккаунта, то транзакция потребила меньше `21000` газа.
Если после выполнения:
```shell
$ registrar.py --add "Mark Zuckerberg"
Successfully added by 0xdc367624ef64a62f72706591235f0eb6f554425cf2724f3636b43ff0a382bc6f
$ registrar.py --del
Successfully deleted by 0xecf27d6236b24f3643fb6f55442572f0a382bc6fc3674ef64a62f706591235f0
```
запустить
```
$ curl -X GET "https://blockscout.com/poa/sokol/api?module=transaction&action=gettxinfo&txhash=0xecf27d6236b24f3643fb6f55442572f0a382bc6fc3674ef64a62f706591235f0" -H "accept: application/json"
```
то значение `gasUsed` будет меньше `21000`.
### Проверка решения
Для провреки решения данного этапа существует возможность использовать автоматическое тестирование. Для этого необходимо создать два [новых проекта на сервере GitLab](https://gitlab.com/projects/new). При создании проектов необходимо использовать специальные шаблоны, которые и позволят выполнять автоматическую проверку.
* [Шаблон GitLab-проекта для задачи "Simple registrar contract"](https://drive.google.com/file/d/1f1JWXsQyc_3hBmU3VnurAaX6Cx9SFk5i/view?usp=sharing)
* [Шаблон GitLab-проекта для задачи "Simple registrar on an Ethereum contract"](https://drive.google.com/file/d/1Onf5RxnsG4wCviqguCwtf0iZngN28AnX/view?usp=sharing)
После создания шаблонов нужно склонировать репозитории на локальную машину.
Имейте в виду, что система проверки решения задачи "Simple registrar on an Ethereum contract" подразумевает, что контракт (задача "Simple registrar contract") располагается в отдельном репозитории и подключен через _git submodules_. Как подключить _submodule_ написано в файле `README.md` в разделе "Подготовка".
Каждый раз, когда будете делать `push` в репозитории проектов будет автоматически запускаться проверка решения. Результат проверки можно будет видеть в GitLab в разделе `CI/CI -> Pipelines`.
## Детальный план третьего этапа
### Входные требования к участникам третьего этапа
Знание базовых алгоритмических конструкций языка и структур хранения данных языка программирования Python.
Умение создавать и отлаживать Python приложения, взаимодействующих с веб-сервисами посредством REST-запросов.
Умение получать посредством [Microsoft Face API](https://azure.microsoft.com/en-us/services/cognitive-services/face/) различные параметры одной фотографии c изображением лица человека.
Умение использовать системы ведения версий Git для разработки программного обеспечения.
### Теоретические знания, получаемые на сборах
Базовое понимание процессов тренировки системы для распознавания лиц и идентификации человека по лицу, последующее получение и интепретация результатов ее работы.
Знание методов, предоставляемых _Microsoft Face API_, для написания системы с функционалом идентификации человека по лицу.
### Навыки, получаемые на сборах
Навык создания и отладки простых приложений на языке Python, производящие идентификацию по лицу с использованием _Microsoft Face API_.
Умение использовать библиотеку [cognitive_face](https://github.com/Microsoft/Cognitive-Face-Python) для взаимодействия с _Microsoft Face API_.
Навыки организации тестирования программного продукта, с фунциями идентификации человека по лицу.
### Оборудование
Ноутбук с web-камерой, с установленным ПО для написания программ на языке Python и python-библиотекой [cognitive_face](https://github.com/Microsoft/Cognitive-Face-Python), также необходим клиент системы ведения версий Git.
Также для каждого участника хакатона необходима регистрация на сервисе Microsoft Azure, а именно необходима [подписка на Cognitive Services](https://docs.microsoft.com/en-us/azure/cognitive-services/cognitive-services-apis-create-account).
### Формат участия
Индивидуальный. Каждый участник самостоятельно решает задачу на своем комплекте оборудования.
### Требования к проводящему
Необходим человек, который имеет опыт разработки приложений с функцией идентификации человека по лицу. Также требуется опыт взаимодействия с web-сервисами посредством REST-запросов. Желателно предварительное знакомство с функционалом _Microsoft Face API_.
Рекомендация - иметь несколько ассистентов для помощи основному ведущему учебно-тренировочных сборов. Общее количество проводящих должно исчисляться по 1 человеку на каждые 8 участников.
### Почасовой план
Учебно-тренировочные сборы расчитаны на 4-5 часов.
| Время | Описание |
| :---: | :--- |
| 15 минут | Знакомство с процессом работы приложения с функционалом распознавания лиц. |
| 30 минут | Рассмотрение [функционала](https://westus.dev.cognitive.microsoft.com/docs/services/563879b61984550e40cbbe8d/operations/563879b61984550f30395236), предоставляемого _Microsoft Face API_ для приложений с функционалом идентификации по лицу. |
| 30 минут | Краткий обзор API, предоставляемого python-библиотекой [cognitive_face](https://github.com/Microsoft/Cognitive-Face-Python). |
| 15 минут | Постановка задачи. Описание ожидаемых входных и требуемых выходных данных. Предоставление требований к публикации кода на сервере ведения версий git. |
| 3 часа | Решение задачи участниками учебно-тренировочных сборов. Приемка работ |
### Описание задачи
Технологии для распознавания и идентификации лиц уже давно интересуют исследователей, занимающихся компьютерными науками. За год произведены наработки, часть которых выложена в публичный доступ в виде исходного кода, еще часть используется в закрытых коммерческих продуктах, а крупные компании такие как Microsoft, Google и Amazon подготовили web-сервисы, которые разработчки приложений могут использовать в своих продуктах. Таким образом, компании, которые только начинают свой путь в создании систем идентификаций человека по лицу, имеют возможность уже на самых ранних стадиях создания продукта демонстрировать основной функционал, не тратя ресурсы (время и деньги) на серьезные исследования и реализацию алгоритмов машинного обучения, решающих данную задачу.
Сервис, предоставляемый _Microsoft Face API_, может быть использован на любых фазах процесса идентификации человека по лицу:
1. [Инициализация группы людей](https://westus.dev.cognitive.microsoft.com/docs/services/563879b61984550e40cbbe8d/operations/563879b61984550f30395244), для последующей идентификации конкретного человека внутри этой группы
2. [Инициализация отдельных людей](https://westus.dev.cognitive.microsoft.com/docs/services/563879b61984550e40cbbe8d/operations/563879b61984550f3039523c) внутри группы
3. [Заполнение примерами лиц](https://westus.dev.cognitive.microsoft.com/docs/services/563879b61984550e40cbbe8d/operations/563879b61984550f3039523b) хранилища для каждого человека
4. [Тренировка сервиса](https://westus.dev.cognitive.microsoft.com/docs/services/563879b61984550e40cbbe8d/operations/563879b61984550f30395249) на идентификацию лиц по загруженным примерам
5. [Идентификация](https://westus.dev.cognitive.microsoft.com/docs/services/563879b61984550e40cbbe8d/operations/563879b61984550f30395239) одного из человек в группе по изображению его лица
Ваща задача - написать приложение на языке Python, которое могло бы идентифицировать человека по изображению лица.
Приложение (python-скрипт) должно:
* идентифицировать одного человека из группы, состоящей не менее чем из 7 людей.
* собирать данные о лице пользователей из видеопотока (файл)
* натренировать систему идентификации на использование собранных данных
* по изображению лица пользователя взятого из видеопотока (файл) идентифицировать его
* сообщать о невозможности идентификации пользователя
Имя исполняемого скрипта должно быть `faceid.py`
Скрипт должен работать с _Microsoft Face API_ через заранее созданный аккаунт на сервисе. Ключ подписки для использования сервиса указывается в файле `msfaceapi.json`:
```json
{"key": "563879b61984550e40cbbe8d3039523c"}
```
Группа пользователей, с которой работает в данный момент скрипт задается через файл `faceid.json`:
```json
{"groupId": "fintech-01"}
```
#### Примеры использования
##### Добавление пользователя (US-01)
Пользователь может добавить нового человека в систему:
```shell
$ faceid.py --name "Elon Musk" video.mpg
5 frames extracted
PersonId: 419e345a-e6d6-4d9c-953d-667787b8d52e
FaceIds
=======
e27558b9-812d-41c3-b114-8e434b8f4602
44c350f2-6653-4616-a1b7-e0fe9b481b6b
f945a3be-4b20-4049-b080-4142a55e4f93
855ab7c2-9bb3-49ed-8cac-1366c0274b08
9c4af288-54cd-4375-8eef-f8c29ed56685
```
Количество кадров для добавления нового человека в систему - всегда 5. Кадры из видео берутся через равные промежутки времени, первый кадр - в начале видео, пятый - в конце.
##### Добавление новых изображений лица пользователя (US-02)
Пользователь может добавить дополнительные изображения лица человека к уже существующим в системе:
```shell
$ faceid.py --name "Elon Musk" video2.mpg
5 frames extracted
PersonId: 419e345a-e6d6-4d9c-953d-667787b8d52e
FaceIds
=======
035cc1f5-2ac3-4099-8af5-2b3f3a25bf55
0479ee7d-0572-4ac8-bc5c-6863efdbb347
bf910059-3944-49cc-b6ac-4ac15cdd8e80
e93568a3-72c8-41f1-a5b0-9547121aa50d
365ffb4f-0bfa-4a99-808e-bb7c1f19237b
```
##### Обратботка ошибок при добавлении лиц пользователя (US-03)
Если при попытке добавить новые изображения с лицом пользователя, на видео нет кадров с лицом пользователя, то выдается ошибка:
```shell
$ faceid.py --name "Elon Musk" video5.mpg
Video does not contain any face
```
При обработке видео, где содержится меньше 5 кадров, должна выдаваться такая же ошибка.
##### Удаление пользователя (US-04)
Пользователь может удалить человека из системы идентификации:
```shell
$ faceid.py --del "Elon Musk"
Person with id 419e345a-e6d6-4d9c-953d-667787b8d52e deleted
```
##### Удаление несуществующего пользователя (US-05)
При попытке удалить незарегистрированного человека из системы идентификации выдается ошибка:
```shell
$ faceid.py --del "Vitalik Buterin"
No person with name "Vitalik Buterin"
```
##### Инициализация системы идентификации (US-06)
Пользователь может запустить обучение системы идентификации:
```shell
$ faceid.py --train
Training task for 7 persons started
```
##### Идентификация пользователя (US-07)
Пользователь может выполнить идентификацию человека по кадрам из видео.
```shell
$ faceid.py --identify video3.mpg
The person is "Elon Musk"
```
Идентификация должна проходить успешно, только если _Microsoft Face API_ для каждого из пяти разных кадров из видео указывает на одного и того же человека с высокой степенью (не менее 50%) уверенности определения.
##### Обработка ошибок идентификации пользователя (US-08)
Пользователь получит сообщение о невозможности идентификации, если _Microsoft Face API_ не выдает в каждом из пяти разных кадров из видео высокую (не менее 50%) степень уверенности определения одного и тогже человека:
```shell
$ faceid.py --identify video4.mpg
The person cannot be identified
```
##### Обработка ошибок инициализации (US-09)
Пользователь получит сообщение об ошибке, если процесс обучения системы еще не завершен:
```shell
$ faceid.py --identify video3.mpg
The system is not ready yet
```