...

суббота, 26 мая 2018 г.

Хранение данных: краткий обзор трендов этого года

На этой неделе мы рассказывали, почему не все из внедряемых «зеленых» технологий в ЦОД эффективны. Сегодня мы предлагаем поговорить о том, что происходит в области хранения данных. По прогнозам Statista, в 2018 году общий объём данных, которые «содержатся» в дата-центрах, достигнет 1450 Эбайт, и в этой области формируются свои тренды, которые нужно знать.


/ фото Aaron und Ruth Meder CC

Корпоративные хранилища: популярность SSD растет


Cогласно IDC, в 2017 году стоимость рынка all-flash в корпоративном секторе выросла на 76%. Доход компаний, работающих в этой сфере, составил 1,4 млрд долларов. При этом продажи гибридных флеш-массивов достигли 2 млрд долларов.

В The Register отмечают, что общий объем поставок SSD увеличится до 313 млн в 2021 году (при 157 млн единиц в 2016). Исследовательская компания Technavio связывает рост популярности и объёмов продаж SSD со снижением цен на устройства. И ожидается, что в 2018 году производители продолжат снижать цены на накопители. Снижение составит от 3 до 6 процентов.

Росту популярности SSD также способствует ряд технологий и продуктов. Недавно мы рассказывали об одном из таких решений — серии накопителей Optane от Intel. В мае 2018 года компания представила новую модель — Optane 905P, которая основана на платформе 3D X Point. Решение будет доступно в двух форм-факторах: HHHL и в корпусе 2,5 дюйма. Ёмкость девайса составит 960 ГБ, скорость последовательного чтения данных — 2500 МБайт/с, а последовательной записи — 2000 МБайт/с.

Среди компаний, которые предпочитают использовать в своих ЦОД твердотельные накопители вместо жестких дисков, можно отметить Calligo, Facebook и Dropbox. Facebook, например, задействуют SSD с интерфейсом PCI-E. Представители организации заявляют, что флеш-память хорошо показывает себя при обработке запросов. А CEO сервиса Calligo Джулиан Бокс (Julian Box) утверждает, что SSD позволяет повысить производительность виртуальных машин и не беспокоиться о физических ограничениях хранилища.

Но HDD пока рано хоронить…


Несмотря на популярность SSD, жесткие диски уходить с рынка не собираются. Изготовители HDD также пытаются увеличить производительность за счет повышения ёмкости диска.

Хотя цена на SSD постепенно снижается, твердотельные накопители пока в среднем в 6,6 раз дороже, чем HDD. В IDC прогнозируют, что к 2021 году ценовой разрыв немного сократится, но SSD все равно будет стоить в 2,2 раза больше, чем HDD.

Многие компании не хотят переходить на SSD, поскольку стоимость хранения в расчете на 1 Гбайт пока слишком высока. Поэтому участники рынка внедряют новые решения, которые бы увеличили производительность и надежность жёстких дисков.

Пользователи YouTube, например, загружают 400 часов видео каждую минуту, и чтобы хранить ролики приходится ежедневно увеличивать объем хранилища ЦОД примерно 1 Пбайт. Поэтому в Google пытаются «переизобрести» HDD-технологию: изменить форм-фактор HDD, увеличить размеры диска, повысить безопасность (за счет использования разных ключей шифрования для каждой части диска), а также пересмотреть оптимизацию на уровне системы.

Другая разработка в этом направлении: HDD с двумя актуаторами от Seagate. Задумка разработчиков в том, чтобы удвоить скорость чтения/записи данных за счет разделения набора головок на 2 независимых блока, которые могут действовать параллельно. Например, физический диск на 14 Тбайт сможет «превратиться» в два логических диска по 7 Тбайт. Кроме того, технология позволит увеличить IOPS с 80 до 160 (при произвольном чтении). Внедрение технологии ожидается в конце 2018 или начале 2019 года.

Помимо этого, продолжается развитие HDD с гелием. Такие диски потребляют меньше электроэнергии и меньше весят (по сравнению с «воздушными» моделями), так как снижается трение при вращении магнитных дисков. При этом, согласно отчету Backblaze, показатель отказов дисков с гелием ниже, чем у обычных HDD. В компании полагают, что в долгосрочной перспективе гелиевые диски выиграют у традиционных систем.


/ фото DRs Kulturarvsprojekt CC

…как, впрочем, и магнитную ленту


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

Чтобы продлить ленте жизнь, некоторые компании даже совершенствуют предыдущие решения и разрабатывают новые. Например, SpectraLogic LTO-8 поддерживает хранение «несжатых» данных объемом 12 ТБайт, а скорость их передачи составляет 427 МБайт/с. Головки для записи на такую ленту используют туннельное магнетосопротивление. Эти решения уже применяются в ленточной библиотеке HPE TFinity ExaScale.

Хранилища будущего


Некоторые ученые решили пойти дальше SSD, HDD и облаков и занялись разработкой принципиально новых систем. Например, исследователи из Гарварда работают над ДНК-хранилищами: им удалось записать в живую бактерию небольшой анимационный фильм.

Для записи и считывания информации биологи использовали систему CRISPR. Она является естественным защитным механизмом, который вырабатывает у бактерий иммунитет к вторжению вирусов. Они захватывают молекулы ДНК вирусов, генерируют так называемые спейсеры и «вставляют» их локус. Ученые закодировали желаемую информацию в спейсеры и передали её бактериям под видом вирусной ДНК. О других разработках в области ДНК-хранилищ мы писали в одном из наших предыдущих материалов.

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

При кодировании в качестве дополнительных значений (помимо классических осей X, Y и Z) используются ориентация оси наименьшей скорости распространения света и фазовый сдвиг. Такое хранилище вмещает 360 ТБайт данных и имеет (в теории) неограниченный срок службы. Оба типа хранилища еще находятся на стадии разработки, и говорить об их массовом внедрении пока не приходится.



P.S. Материалы по теме из Первого блога о корпоративном IaaS:
P.P.S. Несколько свежих постов из блога на Хабре:

Let's block ads! (Why?)

Telegram MTPROTO Proxy — все что мы знаем о нём

image

Сразу после событий с блокировками Telegram в Иране и России, в бета-версиях мессенджера начал появлятся новый тип Proxy, а если быть точным, новый протокол — MTProto Proxy.

Этот протокол был создан командой Telegram для решения проблем обхода блокировок, но так ли он хорош?

Как сейчас?


Основный тип прокси с которым сейчас работает телеграм — socks
У него есть фатальный недостаток: Логин и пароль при подключении к прокси — передаётся в открытом виде, нет, ваш телеграм таким образом «увести» нельзя, но вот заглянуть внутрь прокси и понять, что Иван Иванов пользуется телеграмом — можно.

В тех странах, которые используют DPI для анализа трафика, так и сделано. Это устройство разбирает туннель и смотреть, что же там внутри, если видит запрещенный трафик — блокируем.

Что предлагает Дуров?


MTProto Proxy — протокол семейства MTProto (на нем работает Telegram), решает сразу несколько проблем:
  1. Для подключения вместо логин+пароль, достаточно только пароля
  2. Трафик не отличается от обычного HTTPS/TLS (ну почти)
  3. Пароль не передается до сервера при подключении
  4. Трафик зашифрован
  5. Возможна работа через прокси только Telegram'a (другие приложения работать не будут)
  6. Promoted каналы

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

Только Telegram


Ранее каналы (и боты) делали свои прокси и раздавали их в мир для сохранения аудитории в случае блокировки. Их прокси попадали в глобальные списки прокси и через них осуществлялись рассылки спама и другие нехорошие вещи. С новым типом прокси — вы не сможете нарушить закон, максимум что произойдет — telegram забанит ваш IP адрес.
Пример нарушения закона в случае с socks: Через ваш прокси пытались взломать банк/гос.ведомство, ваш хостер получит официальную жалобу и в самом лучшем случае просто вас заблокирует, в худшем — велкам ту суд.

Promoted каналы


image
Promoted каналы — это такой канал, на который вы автоматически будете подписаны при подключении к прокси, он будет закреплен наверху списка контактов/чатов и его нельзя удалить пока вы не отключитесь от данного прокси.

Грубо говоря, telegram позволяет монитизировать proxy, если раньше вы могли взять прокси от канала X (тк он работает быстрее) но вообще его не читать а пойти читать Y, (а при этом, канал X тратит деньги на поддержку прокси в пустоту), то теперь за пользования прокси вы будете платить подписью на канал.

Таким образом, можно ожидать взрывной рост таких прокси, если ранее создание прокси было больше порывом доброй воли или благотворительностью, то сейчас — чем больше пользователей на вашем прокси = тем больше подписчиков у канала --> рекламу можно продать дороже.

Трафик зашифрован


Запустив Wireshark я пошел смотреть, как же выглядит трафик при работе через прокси. А выглядит он как обычное TCP/SSL соединение (без некоторых пакетов/заголовков которые относятся к https). Другими словами, трафик может маскироватся под такие решения как Cisco Anyconnect и аналогичные решения которые используют TCP+SSL.

Внутри тоннеля — «каша» из шифрованного трафика, трафик зашифрован, как можно догадатся, тем самым паролем/секретной фразой которую вы вводите при подключении. Но не только ей, конечно же, тут используются все возможности SSL/TLS.

Когда будет в продакшене?


На данный момент, MTProto Proxy доступен в стабильной версии Telegram for OS X, Telegram or Android, и в бета-версиях Telegram Desktop, iOS Telegram X.

Похоже мы ждем релиза в «продакшен» данного прокси в клиентах Desktop и обычная iOS версия (не Х) сразу после этого, мы должны увидеть новый пост от команды с рассказом о том, почему это хорошо и как жить дальше.

А потестировать где?


На просторах чатов в телеграмм был найден полу-официальный прокси который прекрасно работает с новым протоколом и (похоже) запущен одним из разработчиков, собственно вот он: t.me/proxy?server=proxy.digitalresistance.dog&port=443&secret=d41d8cd98f00b204e9800998ecf8427e

Но и это еще не все, энтузиасты на Github методом анализа исходников пытаются сделать свои прокси сервера (пока официального еще нет), вот пару проектов.

PS А еще в самой свежей версии библиотеки для VOIP звонков которая используется в telegram найдена поддержка режима конференций, похоже скоро будет сразу два больших анонса.

Let's block ads! (Why?)

пятница, 25 мая 2018 г.

Финтех-дайджест: законопроект о регулировании криптовалют прошел первое чтение, инвесторы уверены в будущем биткоина

В течение недели финтех-рынок вел себя мирно. Тем не менее, есть интересные моменты, о которых стоит упомянуть. Эти события имеют отношение как к зарубежью, так и России. Давайте посмотрим, что там у нас стряслось (спойлер — Госдума собирается начать регулирование криптовалютной сферы).

Наверное, главное событие, во всяком случае, для российского пользователя — то, что криптовалютное регулирование в РФ начинает понемногу набирать обороты. Во всяком случае, во вторник Госдума приняла в первом чтении законопроекты, которые определяют такие понятия, как цифровые финансовые активы, правила их оборота в РФ, заключение смарт-контрактов и процедуру ICO.
В первом чтении все три законопроекта, включая «О цифровых финансовых активах», «О краудфандинге» и поправки в Гражданский кодекс РФ, регулирующие цифровые права были приняты Госдумой.

Документ ввел понятие цифровых финансовых активов, к которым относятся криптовалюты и токены. Кроме того, закрепляется процедура ICO и вид договора «смарт-контракт». Что касается последнего, то он заключается в электронной форме, а исполнение обязательств по нему осуществляется с использованием цифровых финансовых технологий.

Законопроект говорит, что криптовалюта и токен — это имущество, а значит, к ним применимы те же нормы регулирования, что и к любым другим объектам гражданских прав. Но при этом цифровые финансовые активы не являются средством платежа на территории РФ.

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

И, наконец, законопроект «О краудфандинге» регулирует привлечение инвестиций с использованием информационных технологий. Здесь определяются правовые основы деятельности операторов инвестиционных платформ по организации розничного финансирования (краудфандинга).

Еще одна новость относительно криптовалют — то, что инвесторы не теряют надежды на возвращение «большого биткоина», то есть криптотмонеты с высоким курсом. Причем для этого биткоин вовсе не обязательно должен увеличиваться в цене каждый день.


Собственно, биткоин никуда и не спешит, судя по графику

«Мы должны понимать, что биткоину, дабы добраться от $8000 до $25000, необязательно расти каждый день. Помните, что десять самых производительных дней отвечают за всю принесенную биткоином прибыль. Если вы не владели биткоином десять дней в году, вы ежегодно теряли 25% с 2010», — заявил аналитик с Уолл-стрит и сооснователь Fundstrat Global Advisors Том Ли.

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

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

Чтобы с платежной системой все было хорошо, введен в работу катастрофоустойчивый кластер на базе ЦОД Москвы и Нижнего Новгорода с онлайн-синхронизацией баз. В принципе, переход не все банки и заметят, поскольку форматы работы остались примерно теми же. Новая система — более эффективная, быстрая и надежная. Клиенты вряд ли ощутят на себе какие-то изменения, а вот банки — да.

Let's block ads! (Why?)

Протестировать всё: как прошёл Heisenbug 2018 Piter

Если попытаться описать прошедший Heisenbug одним словом, это будет «разнообразие». Спикеры из гигантских компаний и из юных стартапов, темы от тестирования мобильных игр до тестирования блокчейна, доклады с кучей кода и совершенно без кода; наконец, были вообще не доклады, а сессии «birds of a feather».

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

Fuzzing-тестирование и компиляторы


Вы думаете, что у вас очень сложная и ответственная работа? Мы про свою тоже так думали, пока не послушали доклад Максима Казанцева (Azul Systems) и не осознали, каково живётся при тестировании компиляторов.

Во-первых, там пользователи считают «это должно правильно работать всегда»: если ошибку в мобильном приложении люди готовы понять и простить, то ситуация «компилятор внёс ошибку в мою программу» вызывает в лучшем случае недоумение. Во-вторых, от веры пользователей «тут багов не может быть» вероятность их появления не исчезает — даже наоборот, в проекте такого масштаба и сложности бороться с ними ещё труднее обычного. А в-третьих, JIT-компилятор Falcon, над которым трудится Максим, сейчас очень активно развивается — то есть при такой сложности и таких требованиях к качеству надо тестировать очень большие нововведения в очень короткие сроки.

Но при этом доклад был посвящён не тому, через что проходят люди, о чьей работе мы обычно даже не задумываемся. Он был посвящён Fuzzing-тестированию, которое способно помочь как при работе над компиляторами, так и в совершенно других проектах. Суть его в том, чтобы автоматически генерировать миллионы разных тестов с элементом случайности, «вслепую паля во все стороны»: при определённых условиях вероятность попасть окажется выше, чем была бы с медленным прицельным огнём.

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



Zeptolab и автотестирование игр


«Мобильная игра» может звучать не так ответственно, как «JIT-компилятор», но с точки зрения тестирования тоже та ещё задача. Пока в «обычном» мобильном тестировании используют целый набор автоматизированных инструментов, в игровом многие из них оказываются непригодными: у элементов интерфейса нет стандартных view id, на разных устройствах всё может загружаться с совершенно разной скоростью, и вообще много своей сложной специфики.

Неудивительно, что геймдев со стороны может казаться непригодным для автоматического тестирования. И при создании суперхита Cut the Rope компании Zeptolab не помогла идея логировать действия ручных тестеров: да, можно записать, в какой момент с какими координатами произошёл тап или свайп, но этот лог не переиспользовать на устройстве с другим разрешением экрана или менее мощным процессором.

Однако на этом в Zeptolab не похоронили идею автоматизации, при работе над игрой King of Thieves к ней вернулись — и там абстрагировались как от точных координат “в какой пиксель ткнули”, так и от точных временных промежутков, научившись вместо этого определять суть тапа. А теперь Дмитрий Алексеев и Евгений Шумаков рассказали об этом. Любопытно, что на одном из прошлых Heisenbug Филипп Кекс выступал с темой «Как научить роботов играть в игры», но там речь шла про игру с очень прямолинейным геймплеем (дрег-рейсинг) — а у King of Thieves специфика другая. И ещё интересно, что компании пригодился проект Appium: его создатель Дэн Куйаяр на Heisenbug тоже уже выступал.


Тестирование конфигурации и разработчики

За амбициозными задачами вроде «автоматизируем неавтоматизируемое» легко забыть о менее эффектных, но не менее нужных. К счастью, на Heisenbug о них было кому напомнить.

Например, все помнят и думают про «основной» код от разработчиков, осознавая важность тестирования бизнес-логики — а вот то, что относится к конфигурации, может легко ускользать от внимания как «малозначимая вспомогательная сущность». Но Руслан Черёмин напоминал, что вообще-то с этой частью всё в некотором смысле ещё сложнее. Она тоже может приводить к ошибкам, которые стоят бизнесу денег, и при этом она обычно зависит от окружения. А это значит, что вроде бы протестированное «на моей машине» может удивить в продакшне.

Доклад, по сути, развивал тему Андрея Сатарина с предыдущего Heisenbug (перейдя от общего к более частному), а также хорошо иллюстрировал слоган Heisenbug «о тестировании не только для тестировщиков». Руслана давно знают посетители наших Java-конференций (JUG-встречу с ним мы организовали ещё в 2012-м), и тут он давал именно взгляд «со стороны разработчика», а его доклад предполагал, что слово «Java» зрители слышат не впервые.


Яндекс, ВК и краудсорсинг


Сразу две крупных компании на Heisenbug поделились тем, как они для тестирования используют не только обычных штатных сотрудников, но и более широкие круги: Ольга Мегорская рассказала о работе с помощью «асессоров» проекта Яндекс.Толока, а Анастасия Семенюк — о программе VK Testers.

Какие преимущества у такого подхода, какие сложности, и как эти сложности преодолевать? Например, Ольга рассказала, что это позволило расширить «пропускную способность» тестирования и сэкономить на QA-аутсорсе, так что уже многие крупные проекты Яндекса активно используют новый процесс, но без сложностей тоже не обошлось. Использование тысяч «не-тестировщиков» даже для рутинных задач означает, что эти задачи нужно подробно описывать понятным им языком, а разработчики не всегда были готовы это делать. В итоге помогает промежуточная прослойка из «опытных асессоров», получающих тест-кейсы в произвольной форме и переводящей их в понятный подробный алгоритм: им как раз понятно, какие вопросы возникнут у других асессоров.

Как многие участники Heisenbug заметили в отзывах, эти доклады были интересными, но не слишком применимыми для «обычных» компаний: когда у тебя нет ни армии увлечённых лояльных пользователей, как у ВК, ни масштабного краудсорсингового проекта, как у Яндекса, попытки сделать что-то аналогичное могут быть нецелесообразны. Но как раз уникальность этих ситуаций делала и сами доклады уникальными: если про «типичный опыт» можно послушать много от кого, то про подобное — только от этих людей. Как заметила Ольга, при построении своих процессов Яндекс даже не мог учиться на чужом опыте, и приходилось набивать все шишки самостоятельно.


Виталий Фридман и UX


Виталия Фридмана широко знают, но не в тестировочных кругах: основанный им сайт Smashing Magazine для веб-дизайнеров и веб-разработчиков очень ценят в соответствующей индустрии. Его доклады тоже встречают на ура, но обычно на совсем других конференциях. Однако такие важные для Виталия темы, как UI/UX, тоже требуют тестирования, и он выступил перед нетипичной для себя публикой.

Как выглядит элемент «карусель» на турецких сайтах? Почему его лучше не использовать, и если всё-таки использовать, то как? На каком сайте размещено, вероятно, самое длинное в мире сравнение характеристик товаров, и что можно было сделать, чтобы им стало удобно пользоваться? Зачем в таких сравнениях нужна возможность менять колонки местами? Какой рейтинг для товара идеален, если «5.0» ощущается накрученным и лживым? По какому чек-листу «учли ли мы это» стоит пройтись при реализации паттерна «аккордеон»?

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

(А если заинтересовал вопрос про «аккордеон» — у Виталия про этот паттерн есть большая статья, и там в конце приведён упомянутый чек-лист.)



BoF и эксперименты с форматом


Среди докладов было много интересного — однако про формат докладов всё в целом понятно. А был на «Гейзенбаге» и другой формат, ранее на этой конференции не проводившийся. Вечером первого дня, помимо вечеринки и спортивного «Что? Где? Когда?», прошли BoF-сессии (название формата появилось из-за английской пословицы «birds of a feather flock together», примерно соответствующей «два сапога пара»).

Что они собой представляли? Стулья располагаются кругом, часть мест занимают спикеры, часть зрители — и начинается обсуждение заранее заданной темы. Часто ли можно увидеть, как в одном разговоре участвуют сразу и Майкл Болтон, и Саймон Стюарт?

Сессий шло две: на русском языке говорили о тестировании в продакшне, на английском — о вечной дихотомии «использовать готовый инструмент или пилить свой велосипед». Больше зрителей собрал русскоязычный, но довольно живо прошли обе.


Майкл Болтон (и точка)


В принципе, тут можно было бы ограничиться именем, которое в тестировочном сообществе говорит само за себя. Однако бывают случаи, когда при заслуженной репутации человек оказывается не самым ярким спикером. Мы как организаторы ориентируемся на зрительский фидбэк — и когда после самого первого Heisenbug отзывы на выступление Рекса Блэка оказались не особо восторженными, намотали это на ус. Рады сообщить, что с Болтоном всё иначе: его закрывающий кейноут «Testers are their worse enemies» собрал очень воодушевлённые отзывы.

Вероятно, это связано с тем, что Болтон оказался очень «живым»: он абсолютно не забронзовел в своих регалиях, шутит на сцене и вне её, притаскивает на BoF-сессию сразу два стакана пива («меня очень интересует вопрос, сколько стаканов можно эффективно нести одновременно?») и сразу создаёт располагающую неформальную атмосферу.

Но «неформальную» не означает «непрофессиональную»: в своей речи он вдумчиво проходился по тому, что считает серьёзными проблемами. «Люди путают тестирование с простыми проверками сборки. Есть определение программы как “набора инструкций для компьютера”, и я вижу в нём проблему. Это всё равно что давать слову “дом” определение “собранные определённым образом стройматериалы”. Дом разумно определять как место, где живут люди. А программу — как то, что используют люди. Мы зациклены на инструментах тестирования, и я не против инструментов самих по себе, но мы используем их как способ избежать контакта с людьми».


Было ещё много интересного — от рассказа Артёма Ерошенко о следующей версии Allure Framework до доклада Алексея Родионова о том, как в тестировании могут помочь сети Петри. Но продолжать можно было бы так долго, что лучше остановимся на этом моменте. Если забыли упомянуть что-то совсем важное или написали что-то некорректно — принимаем баг-репорты в личку. И начинаем ждать следующего Heisenbug, который пройдёт в Москве в декабре!

Let's block ads! (Why?)

Navigation Architecture Component. Практический взгляд

На недавнем Google IO 2018 в числе прочего было представлено решение, помогающее в реализации навигации в приложениях.

Сразу бросилось в глаза то, что граф навигации можно просмотреть в UI редакторе, чем-то напоминающем сториборды из iOS-разработки. Это действительно интересно и ново для Android-разработчиков.

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


Постановка задачи

Я не буду повторять вводные слова про новый архитектурный компонент Navigation Architecture Component, про настройку проекта и основные сущности в библиотеке (это уже сделал Саша Блинов), а пойду с практической стороны и попробую библиотеку в бою, изучу возможности и применимость к реальным кейсам.

Я накидал на листе бумаги граф экранов с переходами, которые хотел бы реализовать.


Хочу отметить, что навигация в данном случае рассматривается в пределах одного Activity, такой подход я практикую уже не на первом проекте, и он себя отлично показал (обсуждение этого подхода — не цель данной статьи).

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


  1. A — стартовый экран. С него приложение начинает работу при запуске из меню.
  2. Есть несколько прямолинейных переходов: A->B, B->C, C->E, B->F
  3. Из A можно запустить отдельный флоу a-b
  4. Из F можно переходить на новые экраны F, выстраивая цепочку одинаковых F-F-F-...
  5. Из F тоже можно запустить флоу a-b
  6. Флоу a-b — это последовательность двух экранов, где с экрана b можно выйти из флоу на тот экран, с которого был произведен запуск флоу
  7. Из экрана C можно перейти на D, заменив экран, то есть, из цепочки A-B-C, перейти к A-B-D
  8. Из экрана E можно перейти на D, заменив два экрана, то есть из цепочки A-B-C-E, перейти к A-B-D
  9. С экрана E можно вернуться на экран B
  10. С экрана D можно вернуться на экран A

Реализация

После переноса такого графа в код тестового Android-приложения получилось красиво:

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

1. Стартовый экран устанавливается свойством

app:startDestination="@id/AFragment"

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

2. Прямолинейные переходы выглядят и работают тоже правильно

3. и 5. Вложенная навигация легко описывается и запускается как простой экран. И тут первое интересное свойство: я ожидал, что вложенная навигация будет как-то связана с вложенными фрагментами, но оказалось, что это просто удобное представление в UI-графе, а на практике все работает на одном общем стеке фрагментов.

4. Запуск цепочки одинаковых экранов делается без проблем. И тут можно воспользоваться специальным свойством перехода

app:launchSingleTop="true"

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

Тут скрыт первый баг: если открыть несколько раз экран F с параметром app:launchSingleTop="true", а потом нажать кнопку «назад», то будет произведен возврат на экран B, но экран F останется «висеть» сверху.

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

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

Здесь мы подошли к важному свойству UI-графа: на графе нельзя описать переходы назад! Все стрелки — это создание нового экрана и переход на него!

То есть чтобы сделать переход «назад» по стеку, надо обязательно работать с кодом. Самое простое решение для нашего случая — это вызвать два раза подряд popBackStack(), новая навигация здесь ничем не помогает. А для более сложных флоу надо будет выдумывать другие решения.

Navigation.findNavController(view).apply {
    popBackStack()
    popBackStack()
}

7. Заменить экран C на D можно, указав в свойствах перехода

app:popUpTo="@+id/BFragment"

как видите, здесь мы жестко завязали логику перехода между C и D на предыдущий экран B. Тоже не самое лучшее место в новой библиотеке.

8. Аналогично и с переходом с E на D — добавляем app:popUpTo="@+id/BFragment", и работает как мы хотели, но с привязкой к экрану B

9. Как я объяснил выше, возвратов на UI-графе нет. Поэтому возврат с экрана E на экран B можно сделать только из кода, вызвав popBackStack(R.id.BFragment) до необходимого экрана. Но если вам не обязательно именно вернуться на экран B, а допустимо создать новый экран B, то делается это переходом на UI-графе с установкой двух параметров:

app:popUpTo="@+id/BFragment"
app:popUpToInclusive="true" 

Таким образом будет скинут стек до экрана B, включая его самого, а потом сверху создан новый экран B.
В реальных проектах такая логика конечно не подойдет, но как возможность — интересно.

10. Возврат на экран A, как вы уже поняли, невозможно описать на графе. Надо делать его из кода. Но по примеру предыдущего кейса, можно скинуть все экраны и создать новый экран A в корне. Для этого создаем переход из D на A и добавляем специальное свойство

app:clearTask="true"

Теперь при вызове такого перехода, сначала будет очищен весь стек фрагментов.

Остался один неизученный параметр из UI редактора навигации:

app:launchDocument="true"

Я так и не понял его предназначение, а скорее всего он просто не работает так, как заявлено в документации:


Launch a navigation target as a document if you want it to appear as its own entry in the system Overview screen. If the same document is launched multiple times it will not create a new task, it will bring the existing document task to the front.

If the user presses the system Back key from a new document task they will land on their previous task. If the user reached the document task from the system Overview screen they will be taken to their home screen.


Выводы

Из моих экспериментов и небольшого изучения исходников можно сделать вывод: новая навигация — это просто UI обертка работы с фрагмент менеджером (для случая приложения в одном Activity). Всем стрелкам-переходам выдается уникальный ID и набор параметров, по которым совершается транзакция фрагментов на старом «добром» фрагмент менеджере. Библиотека еще в глубокой альфе, но уже сейчас заметны баги, которые прямо указывают на известные проблемы фрагмент менеджера.

Если нам надо как-то повлиять на стек фрагментов и сделать возврат дальше предыдущего экрана, то придется работать по старинке с фрагмент менеджером.

Если вызвать навигацию при свернутом приложении, приложение упадет с классическим
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState

Чтобы совершить навигацию нужен доступ к view для поиска navController
Navigation.findNavController(view)

Именно эти проблемы и решает библиотека Cicerone, поэтому сравнивать их мало смысла. Зато можно объединить! Потому что у Google-навигации есть и полезные стороны:


  • Визуальный граф. Для небольших проектов может быть очень полезной подсказкой.
  • Описание входных параметров экрана и проверка без запуска приложения прямо в студии.
    Для этого надо подключить дополнительный Gradle плагин и описывать обязательные параметры в xml свойствах экрана.

    <fragment
    android:id="@+id/confirmationFragment"
    android:name="com.example.cashdog.cashdog.ConfirmationFragment"
    android:label="fragment_confirmation"
    tools:layout="@layout/fragment_confirmation">
    <argument android:name="amount" android:defaultValue=”0” app:type="integer" />
    

  • Привязка Deep Link к запуску любого экрана из графа.
    Мне не удалось проверить эту фичу, но есть подозрение, что она так же сделана в лоб, поэтому просто будет другой корневой экран, а не полная цепочка экранов, как хотелось бы. Но это не точно.
  • Возможность создавать переиспользуемые части графа — “Nested Graph”. То есть выносить некоторую часть графа во вложенный граф, который можно запускать из нескольких мест.

Тестовый проект

Все эксперименты можно посмотреть и потрогать на Github

Let's block ads! (Why?)

Как мы сделали игру для Highload++ с воксельной графикой и VR

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

О спикере: Александр Хаёров (@allexx) руководит отделом разработки в компании Ingram Micro Cloud. Ребята в команде Александра считают себя не просто отличными инженерами, а называют себя великой командой voxel джедаями, мастерами оптимизации, гуру 3D и повелителями больших данных! [примечание: по аналогии с названиями должностей в LinkedIn и Medium]

Эта классная команда, готовясь к выступлению на Highload++ 2017, решила развлечь аудиторию и сделать что-то новое и интересное для стенда. Поэтому они запилили игру, о создании которой и пойдет дальше речь.

Хозяйке на заметку: со стороны организаторов, мы очень приветствуем усилия по подготовке к участию в конференции. Они многократно окупаются, привлекая участников, и, как выясняется, идут на пользу команде.

Итак, поехали!


Часто, разбирая почту, я просматриваю заголовки информационных лент, где мелькают самые разные новости. Однажды я увидел заголовок «Кто такие инди-разработчики». Почему-то он меня зацепил, и я решил почитать эту статью. Я открыл ее — там было очень много цифр, букв и статистики.
Справка: Инди-разработчики — это люди, которые творят игры без специального бюджета и без финансовой поддержки издателей компьютерных игр.

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

В этой статье я узнал несколько забавных фактов:

  • 97% мифических инди-разработчиков — это мужчины;
  • 60% из них — нет, не одиночки, но делают игры в одиночку;
  • В среднем, чтобы сделать инди-игру, требуется от 1 до 3 месяцев.

Так получилось, что мы тоже начали делать игру.

Почему мы начали делать игру


Мне всегда нравились игры от сервиса Reddit. Думаю, и вы не один месяц своей жизни провели на этом ресурсе.

A social experiment by Reddit


Каждый год Reddit проводит социальный эксперимент, как они это называют. Хотя на самом деле это различные игры для сообщества. В 2017 году социальный эксперимент проходил, как всегда, в начале апреля (на день дурака).

Суть игры была многообещающей. Разработчики Reddit создали картину из 1 000 х 1 000 пикселей. Каждому зарегистрированному пользователю на Reddit, а их несколько миллионов, предлагалось закрасить 1 пиксель этой канвы одним цветом из достаточно широкой палитры.

Мероприятие продолжалось 72 часа, и каждый участник раз в 5 минут мог нарисовать лишь одну точку на экране. Люди создавали разные картинки, боролись между собой, перекрашивая пиксели. Некоторые страны и сообщества объединялись и делали совместную работу.

В конечном итоге получилось интересное панно, из которого кто-то потом сделал пазл, кто-то связал носки с таким орнаментом и т.д.

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

Но для технаря самое интересное находилось внутри, поскольку игра привлекла огромное количество людей — в ней участвовало более миллиона зарегистрированных уникальных пользователей — до 90 тысяч человек одновременно закрашивало пиксели ежесекундно!

Профессионально я занимаюсь разработкой web-сервисов и различных M2M-сервисов, когда сервер общается с серверами. Это на самом деле очень важно и ответственно, но порой немножко скучно. Поэтому новый девелоперский опыт всегда интересен. Я им с вами сейчас как раз поделюсь.

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

The Game


Features


Мы с ребятами собрались и набросали скелет идеи, о чем можно сделать игру. Сначала мы решили идти с козырей и написать классные Features.
  • Однозначно хотелось сделать мультиплеер.

Мы решили, что игра будет сетевая, да еще и массовая, а не в формате разделения экрана.
  • Мы выбрали 3D-графику.

Хотя сделать 2D без опыта было бы, вероятно, проще, команда захотела объема.
  • Решили взять хайповую технологию — пусть это будет Виртуальная Реальность.

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

Так у нас образовался Features set, но без определенного геймплея.

Concessions


Но, подумав примерно недельку, мы решили, что нужно как-то ограничить свои хотелки и пошли на небольшие компромиссы.

  • Нам на самом деле не хотелось писать отдельного клиента, и мы решили, что игра будет браузерная, тем более что мы слышали, что современные браузеры стали очень мощными и позволяют делать 3D-графику.
  • Вторым важным фактором было то, что мы, являясь инженерами, конечно же стремимся к прекрасному, но к графике имеем посредственное отношение. Поэтому идея использовать маленькие воксели или блоки для того, чтобы создавать весь мир и конструкцию, нам показалась некоей панацеей.
  • Наконец, мы решили, что мир у нас не будет бесконечным (хотя я уверен, что вселенная бесконечна) и ограничились размерами 1000×1000×200 вокселей, тем самым немножко упростив для себя техническую особенность игры.

Справка: Воксель (Voxel) — это практически пиксель, но в 3-мерном мире. Например, в игре Minecraft мир представлен вокселями.

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

Gameplay и правила


Кажется, что геймплей — это очень простая вещь! Мы прекрасно знаем, как играть в StarCraft, Doom или Quack. Но когда вы создаете свою игру, у вас возникает огромное количество идей. Эти мысли разлетаются в разные стороны и очень сложно (особенно в команде) договориться о том, как игра будет выглядеть и что в ней будет происходить.

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

  • Нужно найти спот — некое здание — именно поэтому игра называется Urban (Город).
  • На споте есть флаг, который нужно захватить, за это начисляются баллы.
  • Участник, набравший больше всех баллов, получает приз.
  • Игроки могут свободно перемещаться по общему миру и перезахватывать флаги (вариация «capture the flag»).

На этом мы определились со всеми менеджерскими функциями и решили заняться архитектурой.

Архитектура


Так как мы создаем enterprise-продукты, то решили начать с enterprise-архитектуры нашей игры. Мы подумали, что в ней обязательно должны быть:
  1. Игроки.
  2. Специальный стенд для того, чтобы поиграть в шлеме виртуальной реальности.
  3. Браузер, поскольку мы решили, что это будет браузерная игра. Люди будут туда приходить и получать оттуда данные.
  4. Какая-нибудь «хранилка» — ведь у нас многопользовательская игра по сети, нам нужно где-то хранить данные о разных игроках.

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

Проблема репликаций в распределенных системах


Как «хранилка» должна общаться с браузером, где работает игра? Тут начинаются интересные моменты, и я бы хотел вас отвести в более знакомую область.

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

Выделяются два вида репликаций:

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

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

Плюсы и минусы активной репликации:


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

 + Второй важный момент — эта система достаточно эффективна. Действительно, не нужно никакое дополнительное устройство в виде сервера, которое будет принимать, обрабатывать и передавать другим игрокам данные.

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

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

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

Плюсы и минусы пассивной репликации:


 + В отличие от активной, пассивная репликация очень стойкая к десинхронизации. Если что-то пойдет не так, есть специальное устройство — сервер, который может привести систему в норму.

 + Вторым моментом, и зачастую очень недооцененным и важным, является безопасность игр. Недавно появилась игра VKpixel Battle — прямой аналог игры Place от Reddit, в которой тоже можно было разрисовывать доску. Эту игру взломали в течение нескольких часов ( источник ). В пассивной модели безопасность игры заметно легче обеспечить по той причине, что опять-таки есть сервер, где можно много всего контролировать.

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

Мы недолго думали, и, как и разработчики всех современных игр, выбрали пассивный способ репликации. На самом деле сейчас подавляющее большинство игр (порядка 99%) используют пассивную репликацию. Поэтому на нашей мощной enterprise-архитектуре появился еще один компонент — game-бэкенд, который берет на себя задачу синхронизации.

Data Structure


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

Для того, чтобы понять, в чем хранить данные, нужно знать, как их представлять. Наверное, это наиболее важный вопрос, который определяет те или иные критерии. Рассмотрим структуру данных, которая возможна в нашей игре.

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

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

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

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

Если 3-мерный мир представить в виде большого куба, то его можно разделить на 8 частей — окты. Каждую из них можно также делить на 8 секций. Этот механизм позволяет сильно сэкономить на хранении структуры за счет областей, в которых отсутствуют данные.

Здесь есть явный плюс — это более выгодная с точки зрения хранения структура. Минус изначально не так очевиден, но быстро вылезает на практике. Дело в том, что нужно использовать различные кэши. Как правило, все, кто использует октодеревья, жалуются, что это заметно медленнее работает, чем обычные массивы.

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

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

Мы решили, что для нашей игры последний вариант оптимален и выбрали его. После этого выбор хранилища для нас прошел незаметно: мы решили — пускай это будет MongoDB. Я бы сейчас не хотел разводить холивар на эту тему — уверен, что на многих других прекрасных базах данных это тоже можно реализовать. Однако мы имели небольшой опыт работы с этой базой и поэтому решили на ней остановиться для экспериментов.

Протокол взаимодействия между фронтендом и бэкендом


У нас есть некая структура, есть клиенты, наверное, появится какой-нибудь браузер, в котором это все будет отображаться. Но как передавать данные между хранилищем и игрой? Пора подумать о протоколе.

Как мы уже знаем, наш мир представлен в виде параллелепипеда с основанием 1000×1000 и высотой 200. Можно проигнорировать высоту и всегда использовать максимальную высоту в выгрузке. Это сильно упрощает создание игры.

В свою очередь каждый квадрат в соответствии с нашим стандартом мы разбили на чанки 32×32 вокселя внутри.

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

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

Теперь у нас возникают, как минимум, две задачи. Например, мы направляем игрока. Он рождается в мире в некой точке.

  1. Определяем ближайшие чанки, которые игрок может видеть, и формируем радиус. На самом деле это не совсем корректное название. Мы формируем понимание расстояния и смотрим, какое количество чанков это затрагивает. Далее делаем запрос get к базе данных, в котором говорим текущую координату игрока и этот радиус.
  2. Создаем set — блок или кубик на карте. Здесь достаточно просто отправить координаты кубика, который хотим установить.

Это прямые запросы в наше хранилище.

В обратную сторону можно наблюдать запросы об обновлении прочих кубиков.

В данном случае речь идет о том, что, находясь в мире и получив некое его изначальное состояние, мы хотим наблюдать новые кубики, которые создают другие пользователи. Для этого мы подписываемся на события и получаем сообщения типа updated о всех кубиках, которые появляются в игре.

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

Так у нас сформировался протокол взаимодействия.

У нас был небольшой выбор того, как мы можем общаться между бэкендом и фронтендом: HTTP, WebSocket, HTTP2. Мы решили остановиться на WebSocket по понятным причинам — для того, чтобы интуитивно уменьшить потенциальные задержки, которые были возможны.

Также мы подумали, что было бы неплохо получать результаты игры — например, смотреть, кто вошел в игру, какие у него очки. Для этого мы сделали отдельную «вьюшку», которую прикрутили к фронтенду и решили использовать для нее HTTP, чтобы не делать для нее авторизацию и не усложнять этот процесс.

Так у нас сформировался определенный стек в архитектуре. Ключевой точкой взаимодействия в нем стал WebSocket.

Game-backend


Бэкенд, как минимум, можно назвать сердцем нашей системы.

  • Так как мы имеем определенный опыт в web-разработке, мы решили не использовать новых, для нас неизвестных технологий. Мы остановились на Python 3.6 и aiohttp. То есть у нас получился полностью асинхронный сервер.
  • К нему мы добавили измененный loop — это uvloop, который позволяет еще быстрее работать.
  • Так как мы используем MongoDB, нам нужен был какой-то асинхронный клиент. Для этого мы использовали motor, который прекрасно позволяет общаться с MongoDB в асинхронном режиме.
  • Наконец, для того, чтобы выставить наш сервер наружу, мы использовали gunicorn, который разрабатывает на Python.

Так у нас получился вполне традиционный стек, который позволяет
обмениваться данными по нашему обозначенному протоколу.

Game-frontend


Это изюминка нашей игры — то, как игра начинает жить и существовать.

В первую очередь у нас встал вопрос — каким образом мы можем написать игровой движок, как вообще делать игры и как это все работает. После недолгого изучения материала мы поняли, что существует библиотека WebGL, которая позволяет очень многое. Она работает с библиотекой OpenGL, которая уже в свою очередь работает с оборудованием, с драйверами, с видеокартой и т.п.

Поэтому первая мысль была — использовать обычный нативный JavaScript, посмотреть, какой API предоставляет WebGL и начать делать игру. Эту идею мы достаточно быстро отмели, потому что по опыту в web-разработке понимали, что разрабатывать самому web-сервер — очень странная и долгая затея. Тем более у нас не было так много времени.

После недолгих поисков мы нашли JS-библиотеку, которая называется Voxel.js. На самом деле она стала для нас Граалем, потому что представляет очень много инструментов.

Библиотека существует уже более 3 лет, и, как заявляет автор, фактически является tool-kit для создания современных браузерных игр, причем воксельных. В ней присутствует все, что необходимо.

  • Понятие мира, в котором есть оси и координаты;
  • Работа с блоками (вокселями), которые понимают концепцию чанков;
  • Инструменты для создания видеоигр:
    •  ограничивающие многогранники для того, чтобы понимать столкновения, нахождение рядом, работу с объектами и т.п.;
    •  ray casting — метод, который позволяет из 3D-объектов создавать на мониторах вид 2D;
    •  текстуры.
  • Самое главное, есть понятие игрока и его управление. Фактически мы получили уже почти готовую игру!
  • Все необходимые события — цикл создания мира, цикл установки блока и т.д. На все из них можно подписаться и производить свои действия.

Как выглядит весь стек

  • Мы пишем свой код, используя библиотеку Voxel.js — это наша специальная логика.
  • В свою очередь Voxel.js общается с библиотекой, которая называется three.js. На ней я немножко остановлюсь, потому что она является краеугольным и важным камнем во всей этой схеме.
  • Далее three.js уже общается с WebGL, которая фактически встроена в браузер (использует его API).
  • WebGL работает уже с настоящим оборудованием — с OpenGL драйвером, который рисует картинку на мониторе.

На самом деле сцену с использованием three.js, и в частности с Voxel.js, который это использует, произвести на свет не так уж и просто. Хотя кажется, здесь нет ничего сложного ровным счетом.

Посмотрим на код, но не будем заранее пугаться.

Чтобы создать классную 3D-картинку в браузере, нужны на самом деле всего 3-4 вещи:

  1. В первую очередь нужна сцена, как и в обычном мире.
  2. На этой сцене должна быть камера — мы создаем объект camera, в котором обозначаем размеры и максимальное/минимальное расстояние, которое мы видим.
  3. После этого нам нужно устройство, которое будет рендерить — создавать для камеры на сцене то, что мы хотим видеть. Для этого мы создаем render. В данном случае как раз используется WebGL технологии, и наша видеокарта будет трудиться для того, чтобы создать мир.

В принципе, у нас есть все для того, чтобы игра работала. Единственное, не хватает каких-то объектов.

 4. Для того, чтобы создать объект, нам нужны:

  • Геометрия (geometry) — это то, как объект будет выглядеть в пространстве. Например, если это куб, то у него должны быть вершины и грани.
  • Материал (material) — для того, чтобы раскрасить объект. Самый простой вариант — использовать цветную заливку.

Соединив геометрию и материал, мы получим так называемый mesh (или некую сетку объекта).

Дальше вызывается простая функция animate. Как setInterval в браузере, она каждый раз отрисовывает новый фрейм и получается анимация. Фактически этот механизм используется в обычных 3D играх и доступен в браузере.

Виртуальная реальность


Я бы хотел поговорить немножко о VR. Как я уже говорил, нам хотелось использовать хайповую передутую технологию для того, чтобы привлечь внимание. Мы решили использовать VR. Это был случайный, спонтанный выбор, но изучив тему, мы поняли, что VR — это не очень новая и не очень хайповая технология. Эта картинка датирована началом XX века — это VR, но XX века!

Нужно всего лишь использовать этот шлем, чтобы рассматривать настоящие 3D-объекты — единственное, что в статике.

Oculus Rift


Мы решили использовать не статическую картинку, а все-таки создать графику с видео. Поэтому наш выбор пал на Oculus Rift.

Опять-таки выбор был достаточно интуитивный и спонтанный. В нем нет ничего особенного, Oculus Rift представлен, как минимум, 3 базовыми устройствами:

  1. шлем;
  2. специальное устройство для того, чтобы понимать трекинг, то есть движение головы, которое носит вспомогательный характер (слева);
  3. контроллер — источник команд, который может быть представлен разными
    устройствами.

Никто из нас до этого с VR-технологиями и со шлемом Oculus не имел дела.

Плюсы:

 + Это действительно VR-картинка — она вполне настоящая и позволяет обманывать наш мозг и представлять, что мы находимся в 3D-мире.

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

 + Это действительно очень удобное устройство, хорошо сделанное, которое прекрасно лежит в руке и отлично носится на голове. Можно сказать, что это действительно потребительское устройство.

Минусы:

 - Я представлял себе VR так, что можно просто надеть шлем, девайсы и будет классно! На самом деле это огромное количество проводов. Фактически к каждому устройству необходим кабель, а то и два.

 - Второй важный для меня момент и легкое разочарование — я ожидал, что я возьму свой обычный лэптоп и смогу программировать, сидя на диване. Оказалось, что есть серьезные ограничения: можно использовать только Windows, Oculus и SDK не доступен для macOS/Linux. Возможно, это стратегия компании или особенность операционной системы — мне сказать достаточно сложно.

 - Я не смог запустить даже простое видео или игру в VR, не подключая достаточно приличную видеокарту. Я не являюсь ярым геймером современных 3D-игр и поэтому мне пришлось искать ее для того, чтобы начать разработку.

Думаю, что если вас не стесняют эти минусы, то смело можно пробовать современные шлемы виртуальной реальности.

Как делать игры для VR


Для нас эта тема была абсолютно закрыта и непонятна. Мы думали, что нужна специальная магия, возможно, устройства или ученая степень. На самом деле нет.

A-Frame


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

Наверное, первое, что можно найти в интернете, это фреймворк A-Frame. Он является лидером и вообще доминирующим фреймворком для создания дополненной и виртуальной реальности.

Что здорово, он работает с огромным количеством устройств, включая Oculus Rift, и даже с обычными мониторами. Это позволяет работать в режиме совместимости, когда нет шлема, что очень удобно для разработки.

Но, наверное, самое здоровское то, что если вы являетесь web-разработчиком, он будет вам очень близок, потому что использует парадигму и концепцию HTML. Вам не придется компилировать код, не нужны специальные программы — достаточно использовать свой браузер и обычный блокнот для того, чтобы написать первую 3D VR-сцену в браузере.

Код на картинке выше выглядит, как обычная html-страница. Вспомните мой предыдущий рассказ о сцене и рендере, здесь можно увидеть примерно то же самое.

Есть сцена, на которой созданы разные объекты. Рендер и камера заданы по умолчанию, но их можно переопределить. Если вы скопируете этот блок кода, то в своем браузере увидите соответствующую картинку. На ней с помощью мышки или клавиатуры можно перемещаться и увидеть полностью 3D-объекты с тенями и т.п. Дальше можно здорово развиваться, расширяя эту идею.

Так мы начали делать версию для VR.

Вы спросите — а где здесь VR? VR здесь на самом деле находится в правом нижнем углу. На этой картинке этого нет. Там появляется очень маленький значок очков виртуальной реальности. При нажатии на эту кнопку, появляется VR-картинка. Это выглядит абсолютной магией, потому что вы не делаете ничего специально для того, чтобы появилась виртуальная реальность. Это делает за вас фреймворк.

Если посмотреть детальнее, то здесь нет ничего сложного. Для этого достаточно создать изображение для двух глаз и правильно его расположить. Это позволит генерировать правильную картинку.

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

  1. Один для обычной игры с использованием Voxel.js.
  2. Другой — с использованием библиотеки A-Frame.

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

Оптимизация


Напоследок хотел бы рассказать немного об оптимизации.

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

1. Pre-process voxel models

Как я уже говорил, для того чтобы создать мир, мы использовали воксели и программу для рисования вокселей наподобие PowerPoint. Конечно же, те объекты, которые мы создавали, состояли из огромного количества полных кубиков.

Когда этот мир загружался, наша картинка требовала много данных и достаточно медленно работала, поскольку содержала очень много вокселей. Первое, что нам пришло на ум: «Почему бы не сделать объекты полыми, то есть внутри не создавать эти самые кубики? Ведь пользователь их все равно не увидит!»

Мы написали очень простой алгоритм, который позволяет исключать из нашего мира, который мы создали в отдельном редакторе, воксели, которые находятся внутри. Это просто колоссально снизило количество передаваемых данных — примерно на 78% уменьшило количество вокселей в мире.

2. User Mesher

Вторым важным моментом является рекомендация использовать mesher. Дело в том, что, создавая игру с воксельной графикой, мы конечно же в голове у себя представляем отдельные кубики. Но в действительности мир, как и в Minecraft в том числе, устроен немножко по-другому.

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

Кстати, в некоторых фреймворках mesher включен по умолчанию. Так c Voxel.js мы получили достаточно приличный FPC изначально. В A-Frame такого нет, и мы использовали mesher уже дополнительно.

3. Enable compression for WebSocket (RFC 7692)

Наконец, оптимизация из мира web-разработки. WebSocket — отличная технология, но по умолчанию она не производит никаких манипуляций с теми сообщениями, которые передаются с ее помощью.

Мы передавали достаточно большое количество текста (в данном случае JSON) между клиентом и сервером. Эти данные были очень похожи друг на друга. Поэтому у нас возникла идея — почему бы нам их не сжать?

Единственной загвоздкой было наличие WebSocket, а не классического HTTP. Открытием для нас, возможно, это будет также приятным открытием для вас, стало существование специального RFC, который описывает, как можно делать компрессию внутри WebSocket.

Там есть несколько технологий, основанных на использовании специальных плагинов. Фактически включение такой технологии на сервере в нашем случае позволило заметно понизить трафик — буквально с 5 MB передаваемых данных до 1,8 MB.

Приятно, что современные браузеры — такие, как Chrome, Firefox, Safari — поддерживают компрессию со стороны клиента. Вам достаточно правильно включить компрессию на сервере и реализовать ее, и все будет прекрасно работать.

Единственно важным моментом является то, что во всех отладочных инструментах браузера информация по компрессии не отображается, а показывается информация уже раскрытых данных. Поэтому не стоит переживать — компрессия, скорее всего, у вас работает, а данные, которые показаны, уже активны после всех процедур.

В заключении хочу сказать — обязательно пробуйте что-то новое и получайте от этого удовольствие! Заходите к нам и посмотрите, как выглядит наша игра, в статье специально нет ни одного скриншота.

Для любопытных ребят, которым хочется посмотреть кодовую базу, мы сделали ее открытой. Вы можете понаблюдать, как мы разрабатывали игру, что она из себя представляет и даже запустить без проблем свой экземпляр игры, включая сервер и две версии — для VR и просто для браузера.

Кстати, к РИТ++ 2018 ребята готовят ремейк логической игры Pipes — называется CloudPipes.

Что еще раз подтверждает тезис, участие в конференциях, особенно наших, — это весело!

Расписание фестиваля с докладами, митапами, викториной и «Что? Где? Когда?» готово, а у вас еще есть шанс приобрести билет.

Также на забывайте про Highload++ Siberia, которая тоже всего через месяц.

Let's block ads! (Why?)

Простые и мощные краткосрочные смарт-контракты

В последнее время смарт-контракты широко применяются в сети Ethereum в основном для проведения ICO и управления выпущенными токенами. Такие контракты существуют столько, сколько необходимо для обслуживания проектов, при этом месяцами обеспечивают бесперебойное взаимодействие с тысячами клиентов. Будем называть их долгосрочными смарт-контрактами.

Однако определённые задачи требуют, чтобы контракт выполнялся буквально за минуты, после чего он становится не нужен. Причём для каждого пользователя могут понадобиться особые параметры, реализовывать их в рамках большого контракта нецелесообразно. Такие контракты будем называть краткосрочными. Рассмотрим их более подробно в этой статье.

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

Сравним контракт с веб-сайтом. Вы разработали сайт, выложили его в интернет, а провайдер прописал в DNS, что по адресу www.company.com находится определённый веб-сайт. Выкладку контракта в сеть Ethereum можно рассматривать схожим образом: вы разработали код, поместили его в сети (то есть послали специальную транзакцию «создай контракт») — и у контракта появился свой собственный адрес в Ethereum, в точности такой же, как адрес, который вы отдаёте кому-либо, чтобы он переслал вам эфир.

При этом у «сайта» в Ethereum есть полезные для смарт-контрактов свойства:


  • Код «сайта» нельзя изменить. Максимум можно прибить его, если заранее запрограммировать возможность «гибели» контракта при получении специального сообщения. Это не значит, что код исчезнет или смарт-контракт будет стёрт. Просто любая отправленная в него транзакция вернёт ошибку.
  • Каждый запрос к «сайту» — неоспоримая транзакция, навсегда сохраняемая в блокчейне. На ICO вы внесли один эфир и получили десять токенов — внутри контракта появилась запись о том, что у вас есть десять токенов. Ваш запрос изменил состояние контракта. Каждая такая транзакция уже неоспорима технически. Вы всегда сможете доказать, что транзакция была и её подписали именно вы (если есть нужный секретный ключ).
  • Каждый запрос от пользователя на «сайт» может содержать любое количество средств. Если мы рассматриваем контракт как сайт, то каждый запрос к «сайту» способен нести в себе эфир. Представьте себе сайт, где вы можете к каждому клику по кнопкам приложить любое количество денег, а сайт при этом понимает, сколько ему прислано, умеет отдавать сдачу и т. д.
  • Каждый запрос виден всем. Вы не можете ограничивать видимость запросов к «сайту». Вы послали запрос в смарт-контракт, а во время исполнения что-то сломалось — для Ethereum это штатная ситуация, и транзакция, вызвавшая ошибку, всё равно будет помещена в блоки, а майнеры всё равно получат свою комиссию за исполнение кода контракта (из вашего эфира, естественно).

После того как сеть «принимает» код нового контракта (все майнеры проверили код, поместили в блоках, замайнили блок, опубликовали его в сети), контракт получает собственный адрес и может принимать транзакции. Не забываем также, что каждая отправленная в блокчейн транзакция — это данные, подписанные электронной подписью со всеми её преимуществами (как минимум с подтверждением авторства). Зачем здесь блокчейн? Говоря простыми словами, дело в отсутствии shared secret, известного двум сторонам. PIN, голый хеш пароля, небезопасная web-сессия — всё это примеры того, чем может воспользоваться атакующий. В случае блокчейна единственный секрет — это ключ на клиенте, всё остальное не требует ни защищённых каналов связи, ни авторизации. Ну, добавим ещё то, что ни одна из сторон не может сделать что-то незаметно для другой: каждое изменение состояния контракта фиксируется, даже неудавшиеся или зловредные транзакции. Блокчейн фиксирует любую операцию, которая что-то изменяет внутри хранилища каждого помещённого в сети смарт-контракта. При этом операция может быть простой, а может делать и довольно сложные вещи, и любой участник сети абсолютно уверен в том, что код контракта у всех участников работает в точности так же, как и у него на машине.

Даже в минимальном варианте (в краткосрочном виде) смарт-контракты — великолепные инструменты для учёта. Их крайне удобно использовать почти в любых проектах, так как из коробки мы получаем всю систему безопасности и отказоустойчивости. Как мы увидим далее, порой даже минимума штатных функций достаточно, чтобы реализовать множество интересных задач.

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

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

Долгосрочные контракты. Обычно бизнес-модель долгосрочного контракта выглядит так: мы поместили его в сети Ethereum, и теперь тысячи пользователей ходят в контракт и что-то в нём делают. В качестве примера приведём контракт токена. Мы выкладываем в сеть контракт, хранящий балансы пользователей. К нам заходят тысячи инвесторов, и для каждого инвестора информация о количестве полученных токенов кладётся в контракт токена. Каждый раз, когда вы пересылаете токены на другой адрес, вы обращаетесь к одному и тому же контракту, расположенному по одному и тому же адресу, и инструктируете контракт изменить балансы токенов (ваш и получателя).

Контракт тащит в себе большое количество данных и живёт столько, сколько жив ваш проект. Токены внутри него могут перемещаться годами. Никаких ограничений на transfer токенов внутри контракта нет, и он будет работоспособен всегда, пока существует сеть.

Другой пример долгосрочного контракта — Equity (долевое владение). Рассмотрим пример компании, в которой вы раздаёте доли: 10 % Васе, 10 % Пете, а вам — 80 %. Вы хотите, чтобы вся прибыль компании распределялась соответственно: если зашло 100 рублей, Васе и Пете достаётся по 10, а вам — 80. Equity делит деньги на потоке, распределяя входящие средства, и позволяет участникам неоспоримо получать свои доли, заодно фиксируя все платежи и суммы. А ведь планируется, что компания будет работать долго, поэтому вы один раз просите программиста, чтобы он выложил в сеть ваш контракт, а потом годами без дополнительных усилий спокойно пользуетесь контрактом, иногда перераспределяя доли.

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

Если контракт умеет только принимать и отдавать фиксированное количество средств (и выдавать, например, сдачу), то любая успешная транзакция становится аналогом кассового чека, а блокчейн — удобным хранилищем данных об операциях. Получилось провести транзакцию — значит, покупка совершена. Показав ETH-адрес магазина в ФНС, можно пояснить: «Вот наши чеки и наши продажи». Это вообще избавляет магазины от необходимости иметь кассовые аппараты, теперь их забота — регистрировать ключи и адреса, принадлежащие магазину, и обеспечивать их безопасность и возможность смены при взломе. Также можно без особых проблем парой строк реализовать уплату налога прямо при покупке, было бы куда платить.

У одноразовых контрактов есть преимущества и недостатки. То, что контрактов много и они мелкие, сильно повышает стоимость помещения в сети Ethereum, ведь это довольно дорогая операция. Но зато контракты отвечают за относительно небольшие суммы, их существенно легче заменить, попросту перейдя на новую версию. Рисков, связанных с безопасностью, намного меньше в силу простоты кода и малого количества данных. Простота кода также означает дешевизну для пользователей. Есть ещё несколько моментов, но о них позже.

В качестве примеров опишем, скажем, три типа простых краткосрочных контрактов:


  • invoice-paid;
  • commit-reveal;
  • one-time multisig.

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

Фактически перед нами ценник. Представьте, что мы продаём арбузы. Мы выпускаем ценник прямо под конкретный плод с конкретным весом, наклеиваем на арбуз и пишем: «Стоит 1 ETH». После этого нам нужно, чтобы ценник либо принял 1 ETH, либо «сгнил» через сутки: возможно, на следующий день мы захотим продать арбуз за 2 эфира.

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

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

Ещё одна довольно близкая аналогия такого контракта-ценника — выставленный счёт. Поэтому мы и назвали контракт invoice-paid: это два рабочих состояния, в которых он может находиться. В режиме invoice он ждёт оплату, в режиме paid принял оплату и ничего не делает. Третье состояние, когда истекло время жизни (TTL — time-to-live), стандартно для всех краткосрочных контрактов. Истекшее TTL заставляет контракт самоуничтожиться или попросту игнорировать любую пришедшую транзакцию.

Можно поместить полезные данные в invoice-paid, например выставить такой invoice конкретному адресу прямо в момент, когда покупатель решил приобрести товар. В этом случае контракт принимает эфир строго с заданного адреса. В контракт можно добавить хеш любых данных: фотографии товара, id’а объявления на Avito, архива с пакетом документов и т. п.

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

При отправке транзакции в сеть любая нода, передающая транзакцию по p2p-сети, может проанализировать содержимое транзакции до того, как она будет включена в блок. Такая нода может создать собственную транзакцию с большей комиссией, которую block-producer’ы с большей вероятностью включат в блок и которая встанет в списке транзакций выше, чем исходная. Давайте вспомним игру «камень, ножницы, бумага». Играть в неё, напрямую отправляя транзакции, в данном случае нельзя. Понятно, что я не отправлю «ножницы» в контракт: мой оппонент может подсмотреть публичную транзакцию и создать свою, с «камнем».

Решение задачи — в схеме, когда доказывающая сторона (в нашем примере их две, я и мой оппонент) «обещает» в будущем показать некоторое значение, пока секретное (наши «ножницы» или «бумагу»). Для этого мы отправляем в контракт сначала хеш от слова «ножницы» (я), затем хеш от слова «бумага» (мой оппонент). Только затем я могу открыто опубликовать «ножницы», а оппонент — «бумагу». Обмануть тут уже не получится: я открою «ножницы», только когда увижу хеш решения оппонента, то же самое касается его. Смысл этапа размещения хешей хорошо передаёт слово commit, а этапа раскрытия значений — reveal, отсюда и название.

Обязательно надо отметить, что перед вычислением хеша строка («ножницы» или «бумага») обязательно дополняется случайным числом. От криптостойкости числа зависит возможность «угадывать» выбор оппонента по опубликованному хешу, поэтому к его генерации надо подходить со всей серьёзностью. Это число — временный секрет, оно опубликовывается вместе со строкой на этапе reveal, чтобы участники могли проверить корректность хеша.

Давайте рассмотрим вариант контракта commit-reveal для оплаты курьерской доставки. Магазин посылает курьера вместе с товаром к клиенту и хочет, чтобы курьер получил оплату, только если доставит товар за три часа и вручит его лично клиенту. Для этого магазин генерирует секретное слово, создаёт контракт, помещает в него хеш слова и время (три часа), после которого магазин сможет просто вернуть свои средства, отправив транзакцию refund в контракт. Магазин выдаёт курьеру (в его мобильное приложение или браузер) адрес контракта, и курьер видит, что за три часа сможет забрать оплату, если узнает секретное слово. Само слово магазин отправляет по SMS клиенту. Логику контракта описывает фраза «Если курьер пришлёт в течение трёх часов слово — прообраз хеша, использованного при создании контракта, я высылаю средства курьеру».

При конфликте с покупателем магазин может сам разблокировать средства для курьера, попросту отправив тому секретное слово.

Разумеется, для реального использования контракты содержат ещё и модификации — дополнительные данные и проверки, комиссии, пороги входа, динамическое изменение стоимости доставки и т. п. Но основная схема commit-reveal — базовая для построения удобных протоколов взаимодействия бизнес-агентов.

Этот контракт — адрес, с которого можно вывести средства, предоставив N из M подписей.

Предположим, муж и жена решили держать часть семейных сбережений в криптовалюте. Хочется, чтобы контракт принимал и хранил средства, но не давал выводить их из контракта, пока не получит как минимум два из трёх подтверждений — от мужа, жены или банка. Если у жены украдут телефон, муж сможет пойти в банк и, получив подпись банка, вывести деньги. В обычном режиме средства выводятся из контракта, когда и муж и жена предоставили свои подписи. Это крайне удобно, ибо взлом одного из участников не грозит несанкционированным выводом средств.

Вообще multisig может оперировать произвольными N и M, но его вариант «два из трёх» покрывает огромное количество бизнес-задач, где требуется третья сторона. Когда покупаешь квартиру и банк отдаёт ключи от ячейки, только когда получает документы на недвижимость, — это и есть multisig 2/3. Деньги кладутся на multisig-адрес, где участвуют продавец квартиры, покупатель и банк. Банк, как только видит договор о смене собственника, ставит свою электронную подпись. Такой контракт также включает в себя ограничения по времени и, конечно же, комиссию для банка. Для единичных задач, оперирующих большими суммами, разумно использовать именно одноразовые контракты. Уязвимость в огромном универсальном контракте, который будет управлять всеми аккредитивами, может привести к куда более серьёзным последствиям, нежели успешная атака на одноразовый контракт.

Вообще multisig — это как автомат Калашникова, с помощью краткосрочных multisig 2/2 и 2/3 легко реализуются сделки с escrow, сделки, требующие коллективного решения, а дальнейшее добавление функционала в multisig и динамическое изменение N и M — это уже переход к долевому голосованию и управлению (но это тема для отдельной статьи).


  1. Простота и, как следствие, безопасность. В Solidity приходится думать буквально над каждым шагом, любая операция стоит газа, каждый лишний вызов внешнего контракта — это потенциальная уязвимость, именно здесь кроется большое количество проблем с безопасностью. Краткосрочный контракт содержит мало кода и не требует взаимодействия с другими контрактами, поэтому более безопасен, чем его старший долгосрочный брат.


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


  3. Краткосрочные смарт-контракты легко переносить на другие блокчейны. Если вы делаете простой краткосрочный смарт-контракт, то, скорее всего, сможете реализовать его безо всяких проблем на графене, EOS и других платформах. Простая логика — больше вероятность, что это уже реализовано в конкурирующих движках, а значит, разработка дешевле и контракт надёжней.


  4. Очень удобно фиксить. Дыра в токене — серьёзная проблема. Придётся заменять токен и перетаскивать баланс — это стоит огромное количество газа. В случае краткосрочных версий мы не контракты деплоим, а фиксим их версию, а потом просто ждём, пока плохие контракты «сгниют» и будут заменены новыми версиями.


  5. Правильно уничтожая контракты, мы будем чистить local storage на клиентах, оптимизируя используемое место. Тут пока ещё тонкий момент, удаляет ли selfdestruct контракт из storage db физически на клиенте, но, по идее, должен. Это позволит не раздувать сильно объём блокчейна.


  6. TTL. Если мы ищем по блокчейну контракты-ценники и знаем, что они живут не больше суток, то поисковик по Ethereum можно настроить на работу лишь с блокчейном за последние сутки. Это делает такие поисковики удобными и быстрыми, так как данных немного, а работающие с краткосрочными контрактами сайты очень быстрые и функциональные. В противном случае шерстить сотни гигабайт блокчейнов, делая tracking тысяч аккаунтов — непростая задача для программистов.

Не бывает всё очень хорошо. Первая проблема — газ. На каждый деплой смарт-контракта придётся тратить газ. Сервис, которые «пуляет» десятки тысяч контрактов, требует серьёзного исследования и балансировки. В Ethereum сегодня можно послать транзакцию при цене газа 5 Gwei, и она прилетит за минуту. А иногда надо ставить 50 Gwei за газ и ждать час. Те, кто используют смарт-контракты, не очень рады росту курса эфира, ибо это означает удорожание отправки контрактов в сеть. Выкладка контракта в сеть — процедура дорогая, поэтому краткосрочные контракты — удовольствие недешёвое.

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

Вторая проблема — мёртвые, но не добитые selfdestruct’ом контракты. Мы «пульнули» смарт-контракт, заплатили за него, а он умер в блокчейне, ничего не сделав. Это нехорошо для state-database, и мы размышляем, что бы такого придумать. Возможно, скрипты-«дворники» за небольшую комиссию будут вызывать selfdestruct у контрактов с просроченным TTL. :)

Третья проблема — сложная инфраструктура для отправки контрактов в сеть. Управление таким количеством смарт-контрактов, их деплой, мониторинг требует серьёзной надстройки вокруг Ethereum и остальных блокчейнов. Это и поисковик по блокчейну, и автоматический деплоер, и очереди для управления push’ами для мобильных клиентов, а также управление фондами с большими суммами эфира, адресами и ключами. Всё это весьма серьёзная история с точки зрения и безопасности, и архитектуры.



Итак, мы рассмотрели некоторые особенности смарт-контрактов, описали несколько кейcов и немного порассуждали о проблемах и решениях. Строительство платформы, которая сможет поддержать запуск большого количества различных типов контрактов, не жертвуя при этом безопасностью и децентрализацией, уже идёт — это наш проект Smartz.io. Разработчикам и небольшим командам платформа дает возможность заработка при размещении своих DApp-ов, а простым пользователям она предоставляет удобный способ в несколько кликов запустить и начать использовать один из множества полезных DApp-ов для персонального использования. Будем знакомы. :)

Let's block ads! (Why?)