hbs2/docs/todo/refchan.txt

222 lines
13 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

NOTE: on-refchans-tldr
CRDT с контролем прав доступа, но без полного онлайн-консенсуса.
Проблема: участники могут искажать историю после их удаления из
списка авторов.
Решение:
Транзакции требуют подтверждений от нескольких пиров.
Только авторизованные пиры могут подписывать и публиковать транзакции.
Транзакции подписываются автором и пиром, ссылаясь на актуальный ACL/HEAD.
Учитываем только транзакции, удовлетворяющие правилам HEAD.
Принимаем "запоздалые" записи в течение короткого периода после обновления HEAD.
Подход: комбинация CRDT и консенсуса. У нас есть PROPOSE и VOTE,
решения делаются через интерпретацию журнала или дополнительные
транзакции. "Авторы" публикуют только валидные транзакции,
достигая валидности при помощи сообщений эмеферного протокола
(фазы VALIDATE/PRECOMMIT).
NOTE: on-refchans-1
Написал, что фиксация владельцем истории не меняется, и это инвариант.
Смешно получилось.
Коротко:
1) Нам хочется изобразить что-то, желательно CRDT, без
полноценного онлайн-консенсуса, но при этом с возможностью
управлять правами. В идеале и чтения и записи в журнал для
многих авторов.
2) (опущены промежуточные выкладки, плоды, между прочим,
дней страданий и выброшенного на помойку кода)
CRDT такой пишется, но даёт возможность зловредным авторам и
корумпированным ими узлам отравлять историю, поскольку даже
если автора удалили из ACL, он может на своём узле не принять
это обновление и несмотря на то, что его обновления не будут
принимать на добросовестных узлах --- если кто-то придёт
за журналом на его узел, он сможет невозбранно писать
"исторические" записи, ссылаясь на любой ACL/HEAD, где он
еще был
3) CRDT в целом не стоек к византийскому поведению, атаки
на него придумываются легко и быстро
4) Не хочется заставлять владельца канала делать какие-то
действия оперативно, по замыслу -- владелец это просто ключ,
который хранится в сейфе, и на свет выходит, только когда
нужно поменять какую-то существенную метаинформацию, например,
инициирвать форк ну или ACL поменять
5) В общем, нам надо придумать какие-то однозначные правила,
которые бы позволили бы принимать транзакции только относительно
валидного "в сейчас" ACL/HEAD и дать какие-то однозначные правила
интерпретации журнала, которые бы могли при прочтении лога
дать возможность установить, что записи были сделаны в соответствии
с актуальными в моменте ACL.
Решение:
1. Для каждой транзакции требовать нескольких подтверждений от разных
пиров (нод).
1. Писать транзакции в журнал, если есть несколько
подтверждений.
3. ACL устанавливает не только набор авторов, но и набор пиров,
которые могут подтверждать транзакции. Эти пиры подписывают
транзы и постят PROPOSE/ACCEPT. Остальные пиры могут только
транслировать их через Gossip. Неприятное следствие:
журнал будут писать только авторизованные пиры, значит,
количество его экземпляров будет ограниченно ими. Но может,
это и к лучшему.
4. Каждая транзакция подписывается и ключом автора, и ключом
пира и содержит ссылку на актуальный ACL/HEAD, подписанный
владельцем канала/журнала/ссылки
5. При чтении журнала учитывать только те транзакции,
которые удовлетворяют правилам, установленным в HEAD (число
подтверждений)
6. Остаётся проблема, что делать, если приехали записи задним
числом --- если их отвергать, то журналы могут не сойтись,
а если принимать --- то остаётся проблема с отравлением
истории.
Единственное, что тут вижу --- всем нодам принимать
"исторические" записи в течение какого-то периода после
обновления HEAD и не принимать после. Ну типа, за минуту-то
всяко все транзы разойдутся, а позже не принимаем.
Как можно видеть --- этот подход смесь CRDT (однозначные
правила интерпретации журнала) и "онлайн" консенсуса,
тут примерно половина его. "Полусенсус" -- по сути,
есть PROPOSE и VOTE (у нас: ACCEPT), остальные выводы
относительно того, что делать с этими транзакциями
можно делать, или интерпретируя журнал, или вводя
дополнительные транзакции, которые уже обрабатываются
сторонними приложениями. Т.е тут опущены фазы
VALIDATE/PRECOMMIT/COMMIT. Предполагается, что "авторы"
постят уже валидные транзакции, а договориться, какая
транзакция являестся валидной, они должны отдельно,
если им надо, при помощи "эфемерных" транзакций.
NOTE: refchan-log-syncronization-1
что мы тут делаем.
1. Получили merkle лога
2. Надо читать лог, если мы его еще не обработали.
Каждую транзу из него валидировать,
и если мы его еще не обработали --
писать вон в refChanWriteQ
Теперь вот прикол: авторы траз будут верифицированы относительно
"сейчас", а не "тогда". То есть, если к нам едут старые записи,
а мы не знаем, в каком они контексте -- то они будут отвергнуты
относительно "сейчас". То есть еще раз: лог едет, допустим,
старый и некоторым авторам в него писать было можно.
А сейчас --- нельзя. Такие транзакции не пройдут валидацию.
Верно и обратное: если добавлены пермишены для каких-то авторов,
но мы эту информацию еще не получили --- то такие транзакции
будут отвергнуты.
Какое видится решение:
1. Любую метаинформацию обрабатывать отдельно и сразу.
2. Транзакции откладывать, если они валидные, но не прошли
проверку.
Источник метаинформации всегда один --- это владелец ссылки.
"Рано или поздно" метаинформация у всех обновится, и мы перенакатим
отложенные транзакции.
Второй вариант. Поскольку лог транзакций приезжает всегда весь, пусть и по
частям.
Мы можем обрабатывать транзакции из него в контексте тех ACL, что есть в нём
же, а не глобальных. Соответственно, сначала принимаем только те
транзакции, что соответствуют логу.
принимаем все транзакции на обновление метаинформации. Объединяем этот лог и
свой.
Какую мы задачу решаем:
Как принимать или отвергать транзакции в условиях частичной несинхронности
состояния?
Метаинформация (ACL) не имеет контекста сама по себе.
Но всегда имеет контекст в плане принятого журнала -- т.е та
информация, что там определена, та и влияет на приём транзакций
из этого журнала.
Таким образом, у нас есть следующие варианты обработки транзакций.
Вариант 1
1. Принять журнал
2. Обновить сначала метаинформацию из него
3. С обновленной метаинформацией принимать транзакции из него
4. Непринятые транзакции откладывать и пытаться принять их потом
Замечание: если узел прислал журнал, в котором есть транзакции,
которые не соответствуют метаинформации (acl) --- это вызывает
вопросы к этому узлу. Такие транзации нужно отвергать.
Таким образом, мы:
В контексте одного присланного лога:
- Извлекаем метаинформацию
- Обрабатываем транзакции с **этой** метаинформацией
- Добавляем только транзации, которые прошли верификацию
- Помечаем лог обработанным
- Конец.
Итого, как же нам обработать присланный журнал?
1. Скачали журнал
2. Поставили в очередь на обработку, если еще не обработан
3. В процессе обработки:
3.1 Достаём метаинформацию и обновляем стейт
3.2 С сохранённой метаинформацией (из стейта) проигрываем
журнал транзакций.
Что тут плохо:
Стейт глобальный. Если метаинформацию держать глобально,
то она не будет соответствовать тому контексту, в котором существует присланный лог.
Нужно каждый лог обрабатывать отдельно в его контексте.
В чём минусы: он может быть огромный и нас можно легко
зафлудить.
Как решать?
1. Не обрабатывать то состояние, которое у нас уже было.
Мы должны вести историю.
2. Не запрашивать (fetch) лог просто так.
Сейчас инструкция poll ведёт именно к периодическому
запросу. В принципе, если не обрабатывать те логи,
что мы уже обработали, это должно быть достаточно
безвредно, если не очень часто.