mirror of https://github.com/voidlizard/hbs2
210 lines
12 KiB
Markdown
210 lines
12 KiB
Markdown
PEP-03: update-reference
|
||
|
||
Задача: необходимо обеспечить контроль прав доступа при постинге
|
||
блоков (куда? TBD).
|
||
|
||
|
||
Пока существует только BlockAnnounce, который просто декларирует, что
|
||
пир X имеет блок Y.
|
||
|
||
Решение, скачивать его или нет принимает узел на основании каких-то
|
||
своих настроек.
|
||
|
||
Нужно ввести какую-то сущность (reference? topic?) которая даёт
|
||
возможность постить блоки "куда-то", на что бы принимающая сторона
|
||
имела возможность решать - принимать эти блоки или нет, и если
|
||
принимать --- то скачивать данные блоки у узла.
|
||
|
||
|
||
```
|
||
[A] [B]
|
||
| (suggest-ref-update ref (upd sign block) |
|
||
+---------------------------------------------->+
|
||
| | (check sign)
|
||
| | (check perm ACB)
|
||
| (get-blok-size block) |
|
||
+<----------------------------------------------+ (if ok)
|
||
| |
|
||
| (get-block-chunks) |
|
||
+<----------------------------------------------+
|
||
| |
|
||
| (chunk X ...) |
|
||
+---------------------------------------------->+
|
||
| |
|
||
| |
|
||
|
||
```
|
||
|
||
Открытые пока что вопросы:
|
||
|
||
1. Предлагать новую голову топика или предлагать блоки в топик?
|
||
|
||
2. Если предлагать новую голову, сойдется ли вообще когда-либо
|
||
топик?
|
||
|
||
3. Если мы считаем, что
|
||
|
||
```
|
||
|
||
topic ::= set blob
|
||
|
||
```
|
||
|
||
то это даёт нам возможность запрашивать разницу между тем, что есть у
|
||
нас, и тем, что есть у узла.
|
||
|
||
Таким образом, мы можем считать, что "topic" (reference) это merkle
|
||
tree включённых в него блоков + ACB.
|
||
|
||
Поскольку алгоритм упорядочивания блоков может отличаться в
|
||
зависимости от применения, а где-то и не требоваться вовсе, то сами
|
||
блоки могут упорядочиваются исключительно лексикографически (TBD?!) по
|
||
их хэшам. Что приводит нас к тому, что merkle tree данных и merkle
|
||
tree топика это разные вещи (!!!). Так как как данных
|
||
обязателен порядок узлов дерева.
|
||
|
||
Отсюда у нас два выхода:
|
||
|
||
1. Ввести вариант merkle tree где явно задан порядок блоков (файл!)
|
||
|
||
2. Ввести вариант merkle tree, где порядок не задан и определяется
|
||
только самими хэшами. Открытый вопрос --- сортировать тексты хэшей
|
||
или их бинарное представление.
|
||
|
||
Мы можем:
|
||
|
||
1. Получить difference (merkle опять?) между нашим содержимым и
|
||
содержимым пира
|
||
|
||
2. Скачать блоки из difference
|
||
|
||
3. Упорядочить топик
|
||
|
||
4. Получить difference
|
||
|
||
5. Если сошлось, то успокоиться
|
||
|
||
6. Если не сошлось, то вернуться на шаг 1.
|
||
|
||
Если не делать какого-то рода барьеров (аналог высоты в БЧ), то при
|
||
большом количестве узлов, которые пишут данные, данный алгоритм,
|
||
КАЖЕТСЯ, не сходится (доказать или очевидно? При отсутствии какого-то
|
||
рода барьера, обязательного для всех, в любой момент времени может
|
||
найтись узел, который добавит узлы в топик, таким образом, его
|
||
состояние и состояние всех других узлов будет различным. Если мы
|
||
упорядочим состояние между N узлами и этим узлом, то всегда может
|
||
найтись другой узел, который добавит "пост" в "топик" и состояние
|
||
между ним и теми N узлами опять окажется различным.
|
||
|
||
Каким образом можно ввести барьеры?
|
||
|
||
1. Ограничить число узлов, которые могут принимать решение о включении
|
||
блока в "топик".
|
||
|
||
Если их ограничить до одного, а этот один будет определяться тем, что
|
||
он смог посчитать какое-то значение, удовлетворяющее условиям ---
|
||
получится PoW.
|
||
|
||
Если их ограничить N узлами, которые должны подписать транзакцию
|
||
своими ключами, например, k/N ключей --- то получится что-то наподобие
|
||
PoA.
|
||
|
||
Если их ограничить N узлами, которые должны согласовать контент и в
|
||
реальном времени принять решение о включении --- то получится что-то
|
||
наподобие PoS/PBFT.
|
||
|
||
Нам нужен такой способ, который не требует обязательного ответа от
|
||
всех известных уполномоченных участников. Подходит: PoW, PoA (с
|
||
вариациями). PoW требует каких-то издержек на вычисления, что может
|
||
при малом числе участников приводить к каким-то ненужным задержкам
|
||
при добавлении блоков.
|
||
|
||
В данном применении (последовательность постов от ограниченного числа
|
||
участников) у нас нет необходимости решать задачу отсутствия double
|
||
spend, т.к. нет объекта для double spend. Решаемая задача ---
|
||
включать блок в set, или нет.
|
||
|
||
2. Какого-то рода временнЫе барьеры?
|
||
|
||
Например, некие узлы уполномочены выдавать некие токены, зависящие,
|
||
например, от времени, или просто гарантированно уникальные и для
|
||
которых определена последовательность. Тогда нам нужно просто
|
||
гарантировать, что в каждый момент времени будет принят (по некоему
|
||
алгориму) только один такой токен, с неким временем жизни (пока не
|
||
выдан следующий токен).
|
||
|
||
Тогда каждый узел для каждого топика ведёт список известных ему
|
||
токенов.
|
||
|
||
Когда узел предлагает блок --- он запрашивает у авторизованных узлов
|
||
этот токен либо же генерирует его сам, если он сам авторизованный узел
|
||
и сообщает его остальным.
|
||
|
||
При постинге блока постящий узел --- узнаёт токен и включает его в
|
||
предложение блока. Принимающий узел --- узнаёт токен и если
|
||
предлагаемый токен устарел --- то блок отвергается, если не устарел --
|
||
то принимается.
|
||
|
||
Таким образом, мы принуждаем узлы к коммуникациям и синхронизации,
|
||
избегаем ситуации, когда какой-то узел постит блоки сам себе, а потом
|
||
своё состояние выкидывает всем, принуждая всех участников
|
||
пересчитывать состояние.
|
||
|
||
Таким образом, при постинге блока мы:
|
||
|
||
1. Опрашиваем всех известных нам узлов
|
||
2. Получаем с каждого токен
|
||
3. Выбираем токен, который есть у большинства участников
|
||
4. Публикуем блок (рассылаем известным узлам)
|
||
5. Каждый узел, получивший блок --- принимает его, если верны
|
||
доказательства валидности блока (ACB + токен актуален)
|
||
6. Если (и обязательно) в токен ввести что-то хэш от известного состояния
|
||
топика --- то мы обязуем постящую сторону выяснить это состояние,
|
||
то есть, как минимум, скачать этот топик или узнать его состояние.
|
||
То есть, синхронизироваться.
|
||
|
||
|
||
Еще раз: мы не решаем задачу BFT. Может быть, она решается таким
|
||
путём, может быть, нет, неизвестно. Наша задача --- принудить узлы к
|
||
синхронизации перед публикацией своего контента и ввести некий
|
||
порядок для блоков.
|
||
|
||
Можно ли включать в токен время, как естественное, известное всем,
|
||
монотонно возрастающее значение? Никакого Proof-Of-Time не существует.
|
||
|
||
Наша задача --- выбирать актуальные, добросовестные узлы и
|
||
сотрудничать с ними.
|
||
|
||
Вопрос, почему узел должен быть актуальным и добросовестным мы выведем
|
||
за рамки данного документа.
|
||
|
||
|
||
Итого, примерный алгоритм, кажется, выглядит так:
|
||
|
||
1. Посчитать x = f1(известное-нам-состояние-топика)
|
||
2. Узнать текущий токен t = T(топик) у известных нам узлов
|
||
3. Посчитать значение y = f2(t,x)
|
||
4. Опубликовать (разослать всем известным узлам? или тем, с которыми
|
||
разговаривали? или всем, но в приоритете тем, с кем разговаривали?)
|
||
контент, включающий y.
|
||
5. Принимающая сторона рассматривает y, если он актуален (TBD), то
|
||
включает блок. Если нет -- то отвергает.
|
||
|
||
|
||
Более простой вариант:
|
||
|
||
1. Постящий узел включает число, определяемое предыдущим известным ему
|
||
состоянием
|
||
|
||
2. Принимающий узел смотрит: было ли такое состояние вообще когда-либо
|
||
ранее, и если было --- то как давно (Сколько голов тому назад).
|
||
Если было слишком давно (TBD), то блок не выключается, принуждая
|
||
постящий блок синхронизироватьсяи перересчитать число.
|
||
|
||
Если к этому варианту добавить nonce + "красивые хэши" мы получим
|
||
защиту от того, что блоки постятся слишком часто и состояние топика не
|
||
сходится у большинства.
|
||
|
||
|
||
|