Назовём её DMSS (Distributed Metadata Storage System). Ну и картинка конечно — куда ж без этого:


image


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


  • Либрусек. Порядка 300-400 тыс. книг.
  • Архив. Порядка 1.5 млн. статей.
  • Скихаб. Порядка 65 млн. статей.
  • Флибуста. Порядка 400 тыс. книг.
  • PirateBay. Никак не могу найти сколько там всего торрентов. Как будто скрывают. Видел только, что сжатый дамп с magnet ссылками весит 100 МБ. Но учитывая, что magnet ссылка это по сути SHA-1 (20 байт) и такие хеши несжимаемы, то выходит, что всего там 100 МБ / 20 байт = 5 млн ссылок.
  • IMDB. Порядка 500 тыс. фильмов.
  • Spotify. Порядка 30 млн. файлов.

Сами файлы (книги, статьи, аудио, видео) хранить в этой системе не надо: торренты с сид-боксами и VPN и так хорошо справляются с этой задачей. Каталог подобных сайтов хотя никаких разумных законов не нарушает (PirateBay например это просто список SHA-1 хешей — самих файлов там нет), будет так или иначе заблокирован силами правоторговцев даже в странах первого мира. Просто потому что такой каталог больно наступает им на яй доходы.


Что должна уметь такая система


  • Прежде всего никто, даже разработчики этой системы, не должны иметь возможности разводить там цензуру. Даже если им предложат вагон золотых слитков и паяльник кипятильник на выбор. Никаких суперадминов.
  • Возможность добавить каталог. Допустим он будет идентифицироваться своим SHA-1. У нового каталога возможно будут даже модераторы которые смогут разводить цензуру и самоуправство, но во первых будет возможность создавать каталоги без модераторов (то есть даже создатель каталога будет лишь обычным юзером), а во вторых всегда можно будет создать новый каталог и переманить аудиторию, если старые модераторы надоели (идея взята с д3).
  • Возможность найти каталог по его SHA-1. Метаданные (имя каталога например или его описание) там хранить не обязательно, потому что всегда можно завести каталог каталогов.
  • Возможность подписаться на каталог. В этом случае участник выделяет немного места для хранения части этого каталога. Какой именно части участник знать не будет. Таким образом участник будет знать, что он хранит часть, скажем статей по химии, но никаким боком не связан с фотографиями котиков или чем то подобным.
  • Возможность отписаться от каталога. Значит фрагменты данных каталога должны быть промаркированы.
  • Возможность добавить новую запись в каталог. Запись по сути будет списком пар ключ-значение и всё вместе вполне может помещаться в 4 КБ. Одним из полей записи может быть magnet ссылка на файл или например ссылка на запись в каталоге комментариев. Максимальный размер записи и её тип будет в свойствах каталога (кажется придётся хранить метаданные каталога в нём самом). Тип записи это довольно общая штука которая вполне может проверятся самописным скриптом: идея в том, чтобы в каталоге с книгами не допускать гигабайтные файлы с байтами явно не из ASCII таблицы. Если в каталоге есть модераторы, то у них должна быть возможность одобрить или отклонить запись. Возможно нужно что то вроде ACL в NTFS.
  • Возможности удалить запись вроде бы быть не должно, но что если есть модераторы? Думаю, что не будет ничего плохого в том, чтобы разрешить удаление. Если не хочется, чтобы кто то всё удалил, то нужно не создавать модераторов с правом удаления.
  • Редактирование мне кажется тоже лишь усложнит систему не дав ничего взамен. Даже комментарии к записи (которые могут хранится в отдельном каталоге где каждый комментарий это обычная запись) редактировать смысла нет. Мы ведь когда email-ы посылаем не жалуемся, что возможности отредактировать их нет?
  • Поиск. Хотя бы нужно уметь находить все записи с заданной подстрокой или лучше с подстрокой с пропусками (как например сделан поиск файлов в гитхабе). Результат должен быть отсортирован хотя бы по времени. Сложность здесь в том, что мало кто будет хранить полную копию каталога и чтобы что-то найти надо будет фактически сделать поиск в ширину. Как-то не очень эффективно выглядит.

Вроде бы всё?


Основные сложности


  • Связность графа peer-to-peer сети. Эту проблему кажется решил телеграм своими push notifications (надо бы почитать про это). Это проблема исключительно авторитарных стран. В странах где сильны правоторговцы проблем с скачиваением метаданных не будет, а проблема скачивания файлов решается торрентами и сид боксами оплаченными биткоинами (на самом деле можно просто торрентами — посмотрите карту юзеров piratebay), но если уж параноить, то сид бокс сделать не сложно.
  • Флуд. Когда связность сети нарушить не получится, в дело пойдёт флуд. Враг будет загружать много легитимно выглядящих записей. Идея в том, чтобы в каталоге было 99% хлама и пользоваться им было нельзя. Как эту проблему решить я ещё не придумал. Возможно увеличивать задержку после каждой отклонённой записи (если есть модераторы).

Детали реализации


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


Некоторые ноды вполне могут быть чем-то вроде сид-боксов в Эквадоре и они могут хранить почти весь каталог. По этой причине хотелось бы придумать как скрестить такую систему с биткоинами, чтобы мотивировать людей создавать такие сид-боксы. Может быть можно добавить в протокол возможность брать плату за скачивание. Минус: система может оказаться в ситуации когда без биткоинов скачать вообще ничего будет нельзя — 99% юзеров отвалятся сразу. С другой стороны одна нода может скачать мегабайт по цене X, а потом невозбранно раздавать её же по цене X/2 и в итоге цены упадут до цен на трафик в Эквадоре.


Добавление записи


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


  1. Запись как правило будет небольшая: меньше мегабайта. Вычислим её хеш (например SHA-1) и зашифруем (например AES-CBC) этим хешем всю запись.
  2. Зашифрованную запись разобьём на маленькие блоки B[1], B[2], ..., B[N]. Идея в том, что каждый из блоков окажется на нескольких случайных нодах. У каждого блока есть его идентификатор — это его хеш.
  3. У клиента есть список соседей — IP адреса клиентов которые он каким-то образом получил. Через те же push notifications или другими способами. Каждый из блоков B[i] рассылаем на несколько случайно выбранных соседей. Теперь каждому блоку соответствует список IP адресов где есть этот блок.
  4. Строим что-то вроде дерева на основе этих блоков. Для простоты будем строить бинарное дерево. Диапазон B[1..N] разобьём на B[1..N/2] и B[N/2+1..N] и два этих диапазона назовём фрагментами F[1] и F[2]. У каждого фрагмента есть идентификатор — это его хеш. Затем разобём эти фрагменты пополам и так далее. В итоге у нас получится, что есть фрагменты нижнего уровня, которые представляют из себя несколько рядом стоящих блоков, например F[23] = B[4..7]. Есть фрагменты котрые объединяют другие фрагменты, например F[8] = F[23..26]. И так далее до самого верхнего фрагмента F[0] который представляет собой всю запись. По сути мы получили список фрагментов F[1..M] где каждый фрагмент имеет id (некий хеш) и представляет из себя список фрагментов из которых он состоит и при определённой нумерации этот список будет без пропусков: F[i] = F[j..k].
  5. Каждый фрагмент F[i] рассылаем нескольким случайно выбранным соседям. Содержимое посылки будет по сути хешем фрагмента F[i] и списком хешей фрагментов из которых он состоит. В дополнение к этому к каждому хешу фрагмента мы отправим список адресов где он есть (чтобы потом было понятно где их искать). Пример "посылки" будет выглядеть как-то так:

POST /fragments
X-Catalogue: 2bc..332
X-Fragment: 3bc..5ee

23e..443 (11.21.32.44, 23.2.3.1, 44.3.4.5)
e3e..55f (3.3.4.2, 2.11.32.123)
22e..44b (1.2.3.4)

Кстати, предварительно всю запись можно пропустить через т.н. Burrows Wheeler Transform (делается за линейное время), чтобы одинаковые символы в среднем оказывались рядом — тогда будет больше одинаковых блоков и разные записи смогут использовать одни и те же блоки.


Допустим, что какие то из соседей — вражеские серверы которые ловят распространителей "запрещённой" информации. Все эти запросы нельзя проверить на содержание чего бы то ни было. Можно например сначала отправлять фрагменты с адресами, а потом отправлять блоки. Блоки по отдельности расшифровать нельзя (AES-CBC не позволяет расшифровать произвольный кусок в середине). Единственный способ узнать, что находится в записи это взять верхний фрагмент F[0](надо ещё как то догадаться, что это верхний фрагмент), собрать всё это дерево и расшифровать всю запись (хеш её известен).


Если в каталоге есть модераторы, то надо как-то придумать, чтобы сначала запись шла им, они ставили подпись (не ручкой конечно), и дальше все запросы шли с заголовком вроде X-Signature, чтобы ноды могли проверить валидность подписи.


Получение записи по её хешу


Хеш записи это верхний фрагмент F[0]. Нам надо восстановить дерево:


  1. Спрашиваем некоторых соседей есть ли у них такой хеш. Если его нет, то повторяем запрос, но уже с заголовком X-SearchDepth: 2 чтобы они спросили своих соседей (возможно не всех). И так далее пока не найдём или не надоест искать. Если в процессе хеш нашёлся, то нода которая нашла хеш может его закешировать и возможно удалить старые записи — место на диске не резиновое. Ответом будет список хешей фрагментов и адреса где они хранятся (по сути тот POST выше, только в виде ответа 200).
  2. Для каждого фрагмента мы получили список адресов где он лежит. Случайным образом выбираем по одному адресу и идём туда. Повторяем этот процесс пока не построим всё дерево и не дойдём до хешей блоков B[1..N].
  3. Скачиваем все блоки. Собираем их в кучу. Расшифровываем.

Здесь надо напомнить, что скачали мы всего лишь метаданные фильма (например), а не сам фильм. Даже в авторитарных странах это ещё не преступление. Но даже если кому-то очень захочется поймать скачивателя метаданных конкретного фильма, то и это будет непросто: скачивание например списка F[0] это ведь не вся запись, а просто её описание. Придётся сделать так, чтобы клиент был окружён вражескими серверами которые могли скоординированно раздать все фрагменты и блоки и с достаточной уверенностью сказать, что этот клиент скачал содержимое всей записи.


Поиск


Здесь каких то интересный идей у меня ещё нет. Ну кроме разве что опроса соседей с строкой поиска, те опрашивают своих соседей и так далее.


Хотелось бы, чтобы поиск выглядел как перемещение по дереву поиска или дереву суффиксов (этакое распределённое дерево поиска), плюс дерево это как-то само обновляется и т.д. При этом без чрезмерного усложения протокола.


P.S.


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

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


  1. mr_tron
    23.04.2018 12:16

    Вы изобретаете ipfs + ipns + filecoin?


    1. scifinder
      23.04.2018 12:20

      Скорее, storj.io


    1. ankh1989
      24.04.2018 08:56

      Кажется да, это именно IPFS. Велосипед придумывать не надо. А то что я там с хешами выдумывал это давно известный merkle tree. Надо только прикрутить (или найти) поверх IPFS нечто вроде форума по аналогии с торрент сайтами или либрусеком.


  1. kaichou
    23.04.2018 13:24

    Редактирование делать надо по-любому.
    Технически эта задача решается номером релиза (тега).


  1. OldFisher
    23.04.2018 14:02

    … предварительно всю запись можно пропустить через т.н. Burrows Wheeler Transform ..., чтобы одинаковые символы в среднем оказывались рядом

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


  1. ton1
    23.04.2018 16:55

    YaCy где-то рядом — распределенный индекс, dht — но там про поиск по страничкам.


    1. ankh1989
      23.04.2018 21:34

      Туда теоретически можно загрузить тот же либрусек? Ну и чтоб можно было комментарии оставлять.


  1. dedyshka
    23.04.2018 18:15

    Каталог подобных сайтов хотя никаких разумных законов не нарушает (PirateBay например это просто список SHA-1 хешей — самих файлов там нет)
    о, как вы ошибаетесь…
    если у вас просто список, например книг — это не нарушает закон,
    а если к этому списку прилагаются ссылки на ресурсы где можно скачать, то ваши отговорки в суде никого волновать не будут.


  1. Closius
    23.04.2018 19:02

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


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

    Так как львина доля пользователей не шарят в программировании, то они не заметят эксплойтов или неправильности реализации. Следовательно также отдельно надо проводить голосование среди шарящих людей (разработчиков).


  1. kAIST
    23.04.2018 22:34

    Как связаны "авторитарные страны" с ситуацаией, когда блокируют незаконный пиратский контент? Его блокируют как бы и в "демократических" странах.


    1. ankh1989
      24.04.2018 06:08

      Разница в методах: в авторитарной стране будут банить любыми средствами, тогда как в странах первого мира будут соблюдать формальности.


  1. robux
    24.04.2018 22:52

    Флуд. Когда связность сети нарушить не получится, в дело пойдёт флуд. Враг будет загружать много легитимно выглядящих записей. Идея в том, чтобы в каталоге было 99% хлама и пользоваться им было нельзя. Как эту проблему решить я ещё не придумал.

    .
    Читать мою статью "Сеть доверия" и другие мои статьи.


    Поверх HTTP

    .
    HTTP — клиент-серверная архитектура, концепция p2p с HTTP не совместима, т.к. браузер оперирует веб-страницами, а не записями. Должно быть отдельное (желательно десктопное) приложение, типа aMule или RetroShare, в котором обмен происходит не веб-страницами, а записями.


    И ещё, истинно децентрализованная система должна соответствовать двум критериям p2p.


    1. Bal
      25.04.2018 17:28

      Только по этой ссылке ZeroNet отнесён к федеративным решениям, а это именно децентрализованная система, отвечающая обоим критериям :)