Дерево состояний позволяет хранить только наборы данных, которым можно заранее присвоить идентификатор или адрес в виде 8-байтового числа. По этому идентификатору они и адресуются.
Например, каждый аккаунт имеет свой идентификатор, который рассчитывается по публичному ключу. Этот идентификатор и выступает адресом объекта в рамках дерева состояний. Для того, чтобы однозначно определять состояние аккаунта в конкретный момент времени, все состояния аккаунтов объединяются в хеш-дерево состояний. В дальнейшем, вершина дерева состояний используется как идентификатор общего состояния приложения.
Разряженное дерево Меркла
В целом, дерево состояний похоже на дерево Меркла. Классическое дерево Меркла ориентировано на хранение фиксированного списка элементов или на хранение хронологически добавляемых элементов, т.е. идет сплошной поток элементов без разрывов.
В дереве состояний хранится относительно немного элементов, но при этом имеется четкая область значений и конкретный адрес каждого элемента. После чего эти элементы объединяются в дерево Меркла. Мы называем это “разряженным деревом Меркла”.
Дерево состояний представляет из себя бинарное дерево, в котором для каждого состояния элемента есть четко закрепленная позиция (задаваемая по ID элемента).
Дерево строится по следующим принципам:
ID элемента однозначно определяет лист, в котором должно храниться состояние этого элемента. В листе дерева хранится текущее состояние элемента.
Для каждого листа и узла рассчитывается его хеш.
Хеш листа рассчитывается по содержащимся в нем данным (т.е. по состоянию элемента).
Хеш узла рассчитывается по хешам левого и правого поддеревьев. Если левого или правого поддерева у узла нет, то хеш равен хешу того поддерева, которое есть.
Благодаря подобной структуре удалось достичь:
Хранение состояния элемента для каждого момента времени (история изменений).
Минимизация времени получения значения элемента по его идентификатору.
Минимизация изменений в дереве состояний с течением времени (изменения затрагивают только новые или измененные листы и “путь” от них до вершины дерева).
Помимо быстрого доступа к состоянию элемента, дерево состояний обеспечивает дополнительный уровень валидации состояния сети.
Если после обработки блока данных, хеш вершины дерева состояний не совпал с тем, что получилось на удаленном пире, то набор данных не принимается, т.к. он был по-разному обработан на разных пирах.
Пример работы разряженное дерево Меркла
Например, дерево состояний для 16 (2^4) элементов выглядит так (в реальном дереве 9’223’372’036’854’775’808 (2^64) возможных позиций):
Следует различать виртуальное состояние дерева и его реальное представление. Например, для дерева из 1 элемента (с ID A-0101) будет фактически храниться только 1 лист (Virtual - виртуальное представление дерева, Real - реальное, которое будет использоваться для поиска данных в снапшоте (текущем срезе)):
Если же происходит изменение состояния существующего элемента, то изменяются только узлы по пути от вершины до этого элемента (например, изменилось состояние A-1010):