idec.talks
Всем привет

Я познакомился в ii/IDEC только в августе этого года, стал изучать как оно всё устроено и наконец на днях, воспользовавшись открытой реализацией ii-php, поднял свой узел - теперь у меня есть несколько мыслей по возможному будущему этой системы (либо системы, которая может отпочковаться от этой системы, но будет оставаться совместимой со старым IDEC API):

1) Кроме base64 существует чуть более компактный способ представления бинарных данных в виде текста - это алгоритм ascii85, когда каждые 4 байта представляются 5-значным 85-ричным числом, где каждая "цифра" это символ от '!' до 'u', плюс буквы 'z' и 'y' несут особый смысл, кодируя четвёрки нулей и пробелов соответственно - в результате данные раздуваются не в 4/3=1.33 раз, как в случае base64 (или uue), а в 5/4=1.25 раз или меньше, что как минимум на 6% компактнее. Можно немного развить ascii85 для кодирования произвольных бинарных данных, назвав новую систему кодирования скажем ascii85+ задействуя остальные неиспользованные символы: 'x' может кодировать четвёрку 0xFF (это может помочь при кодировании прошивок ПЗУ), 'w' - четвёрку 0x80 (это может помочь при кодировании 8-битных беззнаковых WAV-файлов), 'v' - пока может использоваться для детектирования ошибки, фигурные скобки { и } могут выделять закодированный бинарный блок в тексте (наличие явно заданного стартового символа упрощает парсинг, а наличие явно заданного терминатора поможет обрабатывать пограничные ситуации, когда концовка файла не влезает в 4 байта целиком), а ~ и | могут использоваться для каких-то особых случаев (см.ниже). Этот подход можно использовать для встраивания бинарных файлов в текст сообщений как вложений (аля ююки), указывая имя файла после втавки (чтобы клиент знал с чем этот файл надо есть и надо ли):

====
Посмотрите на эту весёлую картинку:
{Abhdhj!$^390+-
...
Bhdbdfjg}=funny.gif
====


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

2) Этот же ascii85+ можно использовать для уменьшения размеров бандлов на 6% сделав новый вызов в API - например /u/n/msgid/msgid/msgid... (вместо /u/m/... который может остаться для старых клиентов) - и результат работы этого вызова может выглядеть примерно так:

====
msgid:{!"#$%&'()*+,-...}
msgid:{0123456789...}
msgid:{ABcded...}
====


где в фигурных скобках будет ascii85+ сообщений (этот алгоритм не является url-safe, поэтому в других местах API где надо url-safe останется всё тот же base64url).

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

4) Хэш msgid может быть не визуально рандомным как сейчас, а будет способным нести информацию о типе (или о версии) сообщения - например сервер принимая от клиента текстовое сообщения классического вида добавит в его список тэгов новый тэг trick/0 и посчитает хэш сообщения - елси хэш не начинается скажем с символа '0', то алгоритм инкрементирует значение в этом тэге (trick/1) и считает хэш ешё раз - если опять не стартует с '0', то инкрементируем ещё раз и т.д. пока хэш не станет начинаться с нуля (в среднем на подготовку "красивого" msgid должно уходить порядка 32 вычислений хэша - иногда меньше, иногда больше) - в этом случае все узлы точно будут знать, что все "новые" сообщения с msgid вида 0... являются новыми "обычными" сообщениями (чтобы отличить от старых сообщений с именами случайно начинающимися с 0 можно проверить наличие тэга trick в заголовке сообщения - если он есть, то это новый тип сообщения с возможными вложенными файлами). Если каждая точка системы точно знает, что это новое сообщение, то она также может проверить целостность сообщения пересчитав его хэш и сверив с msgid ( ведь новый стандарт должен будет явно запретить редактирование или подмену сообщения уже сохранённого узлом ; ). Старые узлы и клиенты будут передавать такие сообщения как самые обычные (если не запнутся на неизвестном тэге trick).

5) Тип сообщения 1... может обозначать закодированный бинарный файл, когда в теле сообщения нет текста, а сразу идёт блок ascii85+ {...}. При посылке такого сообщения отправляющий клиент может задать новое ключевое слово @crc32:0xFFFFFFFF для указания контрольной суммы, которая при сохранении сообщения будет вставлена узлом в строку тэгов в виде .../crc32/0xFFFFFFFF и которую принимающий клиент может проверить после восстановления файла. Размер такого сообщения по понятным причинам будет ограничен - может быть даже придётся уменьшить текущий лимит 87кб до 32кб, чтобы эта реализация была совместима с ограниченными размерами памяти недокомпьютеров, которые могли бы участвовать в работе сети - в этом случае размер самого большого бинарного файла, который можно таким способом отправить, будет составлять порядка 26кб. Старые узлы и клиенты будут показывать такие сообщения как обычные текстовые.

6) Тип сообщения 2... может обозначать составной объект, когда ранее отправленные сообщения типа 1... на самом деле являются кирпичиками, из которых строится большое сообщение. В теле такого сообщения могут перечисляться как блоки {}, так и ссылки на внешние сообщения типа 1:

====
~1gjkwui4iuwqrezD56az
~1ui4iuwqrezD56azFejs
~{......}|это вставка блоба ascii85+ (комментарий после | до конца строки)
~1uwqrzFejsDSGFeekjkd|это ссылка на другой объект, который должен быть вставлен при сборке
{....}=666.bin|это объявление именованного блоба (без вставки)
~666.bin
~666.bin
~666.bin|это вставка копии именованного блоба (всего 3 копии подряд)
====


в примере выше показано как можно повторять несколько раз бинарный кусок, объявленный в том же сообщении (666.bin). Такой тип бинарного сообщения снимает любые ограничения на размер передаваемого объекта, который перед передачей может быть порублен на кусочки. При отправке такого сообщения также может быть использовано ключевое слово @crc32, которое как и в предыдущем случае будет вставлено узлом в строку тэгов при сохранении. Старые узлы и клиенты будут показывать такие сообщения как обычные текстовые (как в примере выше). В случае реализации сообщений 1 и 2 типов на уровне сети для передачи бинарных данных отпадёт необходимость в поддержке файлэх, которые выглядят несколько неестественно применительно к ii (например они не приспособлены для пересылки через последовательные каналы передачи данных, в то время как все остальные подсистемы IDEC представлены в текстовом виде и могут быть использованы через интерфейс терминала).

7) В будущем при отправке сообщения от поинта узлу к ключевым словам можно будет добавить ещё и подпись @sign:0xFF...FF по алгоритму скажем HMAC-RIPEMD-160-96 (с одним секретным ключом известным отправляющей и принимающей стороне), если достаточно удостовериться в валидности посланного от поинта на свой узел (узел должен знать секретный ключ поинта - точно также как сейчас он знает пароль) и далее при сохранении сообщения на узле (после проверки валидности) такую подпись можно опустить, либо (в будущем) по алгоритму Ed25519 (с публичным и секретным ключами), если требуется проверка достоверности сообщения в пределах всей сети на любом узле и любом клиенте (это более тяжёлая реализация, которая требует наличия двух алгоритмов SHA512 и Curve25519, а также способов передачи публичных ключей всех активных участников сети на все вовлечённые узлы) - в этом случае sign/0x... переедет в строку тэгов для проверки достоверности послания в любой точке сети (и также для проверки целостности данных вместо CRC32), а старые узлы и клиенты просто будут игнорировать этот тэг, как неизвестный.

8) Когда сеть разрастётся, возможно придётся отказаться от хранения всех сообщений на каждом узле (в идеале - когда все фетчат всех) - узлы могут быть разбиты на группы (с избыточностью) для хранения разных наборов объектов (скажем в зависимости от значений 2го и 3го символа в msgid). Существуют разнообразные алгоритмы распределённых хэшей, которые можно применить в данном случае для поиска объектов по хэшу (msgid) на сети ненадёжных узлов. В этом случае сеть можно будет использовать как распределённое хранилище подписанных объектов, которые можно будет задействовать при построении распределённых сайтов, мультиплеерных игр, криптовалют и т.д. Для старых узлов можно предусмотреть механизм, когда они подписываются на специальные скрытые эхи, в которые будут транслироваться копии объектов по группам - в этом случае эти узлы будут продолжать работать в старой парадигме IDEC, но в то же время они будут полезными в рамках новой распределённой сети объектов, раздавая сохранённые на них объекты при необходимости по запросу.

Shaos