Вики ZooBC
Данные и хранение

Наборы данных

Набор данных — простейший способ поместить данные в ZooBC: небольшая запись, имя свойства и его значение, которую один аккаунт записывает под каким-либо аккаунтом, обычно под своим собственным. Каждый узел хранит строку как часть состояния цепочки, поэтому любое приложение может прочитать её через API любого узла. Приложения используют строки для профилей, настроек, уведомлений о релизах, счетов и иконок токенов.

Строка

Транзакция SetupAccountDataset (тип 3) записывает одну строку, ключ которой состоит из трёх частей:

  • сеттер — аккаунт, который отправляет транзакцию;
  • получатель — аккаунт, под которым находится строка, обычно сам сеттер (пустой получатель тоже допустим в качестве ключа);
  • свойство — имя длиной от 1 до 256 байт, никогда не пустое.

Значение содержит до 4 096 байт в пределах тела транзакции не более 65 536 байт. Строки версионируются: повторная запись того же ключа заменяет текущую строку, а RemoveAccountDataset (тип 259) делает строку неактивной.

Одна строка набора данных: кто её записал, под кем, свойство и его значение — внутри объекта, который платит аренду.
Одна строка набора данных: кто её записал, под кем, свойство и его значение — внутри объекта, который платит аренду.

Строка публична: прочитать её может любой, поэтому набор данных — не место для секретов. Не годится он и для хранения большого файла. Небольшие файлы идут в файлы DFS, крупные — в пул хранения.

Важно, кто записал

Любой аккаунт может записать строку под любым получателем, и получателя никто не спрашивает — точно так же, как любой может отправить платёж на любой адрес. Поэтому строка — это утверждение, которое её сеттер делает о получателе. Цепочка доказывает, кто это сказал и когда; знать, истинно ли утверждение, она не может.

Узел перечисляет строки аккаунта по адресу GET /api/v1/accounts/<address>/datasets, с необязательным фильтром ?property=<prefix>. Список возвращает каждую строку, в которой адрес является сеттером или получателем, и каждая помечена своей ролью, role: сеттер, получатель или оба. Приложение, которое находит «verified = yes» под пользователем, должно принимать это, только если сеттер — аккаунт, которому оно доверяет, например его собственный аккаунт верификации, и должно отвечать «не верифицирован», когда такой строки нет (данные цепочки — недоверенный ввод).

Две строки говорят «verified = yes»; засчитывается только та, которую записал доверенный сеттер.
Две строки говорят «verified = yes»; засчитывается только та, которую записал доверенный сеттер.

Объекты и владельцы

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

  • Передача происходит в два шага. Владелец отправляет TransferDataset (тип 42), называя нового владельца, и цепочка лишь записывает ожидающего владельца. Передача завершается, когда этот аккаунт отправляет AcceptDataset (тип 44). AcceptDataset от кого-либо другого или для объекта без ожидающего владельца — оплаченная пустая операция: комиссия взимается, и ничего не меняется. Поэтому никто не может навязать объект, а вместе с ним и его аренду, аккаунту, который об этом не просил, а прежний владелец остаётся владельцем, пока новый не примет объект.
  • Удаление. DeleteDataset (тип 45), отправленная владельцем, деактивирует все строки объекта, а депозит объекта переводится в пул долголетия.
  • Политика. SetDatasetPolicy (тип 43) записывает на объект режим управления (только владелец, белый список, чёрный список или открытый) и список доступа, но ни одно правило консенсуса их не читает, поэтому они ничего не ограничивают.

У каждого объекта также есть адрес депозита: аккаунт типа 10, записываемый как ZBS_…, байты которого — 0A000000, за которыми следует идентификатор объекта. Любой может пополнить его обычной транзакцией SendZBC, так что группа пользователей может вместе поддерживать жизнь общей записи. Это обычный пополненный аккаунт, поэтому он также платит аренду аккаунта. GET /api/v1/dataset-address/<hash or ZBS_ address> показывает его.

Аренда

Раз в расчётный период, 172 800 блоков (около 30 дней) в mainnet, цепочка взимает с каждого объекта плату за байты его активных строк:

bytes = sum of (property + value) over the object's active rows
rent  = ceil(bytes × price per MiB ÷ 1,048,576), then × storage multiplier, rounded up

Начальная цена — 5 000 000 атомарных единиц (0,05 ZBC) за МиБ, а множитель хранения начинается с 1,0. Ровно один МиБ строк платит ровно 0,05 ZBC за период. Строка со свойством в 14 байт и значением в 300 байт, всего 314 байт, платит 1 498 единиц: 314 × 5 000 000 ÷ 1 048 576 — это 1 497,27, а каждый этап расчёта округляется вверх.

Аренда берётся сначала из депозита, затем с баланса владельца. Если вместе они не могут заплатить, все строки объекта деактивируются, а оставшийся депозит уходит в пул долголетия. С получателя никогда ничего не взимается. Вся аренда наборов данных зачисляется в пул долголетия, который в каждом блоке выплачивает узлам долю; ZBC никогда не сжигаются.

Расчётный период следует интервалу снимков. Цену устанавливают голосованием места, и её можно снизить до одной атомарной единицы; она меняется раз в период снимков, в пределах ограничений, к среднему голосов учтённых мест (голосования по ценам).

Зарезервированные префиксы

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

ПрефиксПравило
dfs: и dfs:dir:записываются только тремя типами транзакций DFS; SetupAccountDataset с таким префиксом отклоняется (файлы в цепочке (DFS))
tokenicon:изображение PNG или WebP, указывающее ширину и высоту от 1 до 512 пикселей, длиной от 16 до 4 096 байт
inv:объект JSON без единого отрицательного числа, так что счёт не может нести отрицательную сумму; действует с блока 0

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

См. также