Перейти к основному содержимому
Блокчейн66ГЛАВА 66Состояние аккаунта: словарь вместо переменныхgruppaIS-21ball5dopusktruez_z-1…type 12пишем только к себе

Состояние аккаунта: словарь вместо переменных

Прочитано0%
Квизы0/4
Тренажёрыне пройден0/1
Уровень 1 · Новичок

Зачем это нужно​

В Ethereum данные контракта живут в его собственных полях. В Fabric — в общем хранилище «ключ — значение», доступном через объект контекста. В Waves сделано третье: у каждого аккаунта есть свой словарь, и писать в него можно вообще без всякого кода, обычной транзакцией.

Это неожиданно удобно. Прежде чем писать смарт-контракт, можно уже вести журнал: записывать оценки, статусы поставок, показания счётчиков. И это же хранилище потом читает и меняет dApp — то есть данные и код разведены.

Эта глава — про этот словарь: что в нём можно хранить, сколько это стоит и где границы. Все числа ниже сняты на локальном узле Waves 1.6.4.

Словарь аккаунта​

У КАЖДОГО АККАУНТА СВОЙ СЛОВАРЬ3M5HPFG1r9q79uxff6rm1Z…gruppa"IS-21"ball5dopusktrueключи отсортированы по алфавиту3MPLLnbwVqT74cC4K9XK85…[]пусто — но аккаунт существуетчужой словарь трогать нельзязапись всегда идёт в свой аккаунт: адрес получателя в транзакции данных не указываютчитать при этом может кто угодно — состояние публично внутри сети
Свой словарь у каждого аккаунта; писать можно только в свой, читать — любой

Пишем три значения:

const { data } = require('@waves/waves-transactions');

const tx = data({ data: [
{ key: 'gruppa', type: 'string', value: 'IS-21' },
{ key: 'ball', type: 'integer', value: 5 },
{ key: 'dopusk', type: 'boolean', value: true },
], chainId: 'R' }, seed);
тип: 12 | комиссия: 100000
в блоке: 28
Нажми на часть выражения

Читаем:

curl http://127.0.0.1:6869/addresses/data/3M5HPFG1r9q79uxff6rm1Z3UFZcXXXHX32p
[{"key":"ball","type":"integer","value":5},
{"key":"dopusk","type":"boolean","value":true},
{"key":"gruppa","type":"string","value":"IS-21"}]

Порядок — алфавитный по ключу, а не тот, в котором записывали.

Важно

В транзакции данных нет получателя. Запись всегда идёт в словарь того, кто подписал. Это главное правило: чужой словарь не изменит никто, включая владельца узла. А вот читать может кто угодно — состояние публично внутри сети.

Четыре типа значений и удаление​

ЧЕТЫРЕ ТИПА ЗНАЧЕНИЙ И ПЯТЫЙ СЛУЧАЙinteger5целое со знаком, 8 байтbooleantrueда или нетstring"IS-21"текст в UTF-8binarybase64:AbCd…произвольные байты{ key: "ball", value: null }без типа и со значением null — ключ удаляетсядробных чисел нет: цену хранят целым и договариваются, где запятая
Четыре типа плюс особый случай: значение null удаляет ключ
ТипПримерЧто это
integer5целое со знаком
booleantrueда или нет
string"IS-21"текст в UTF-8
binarybase64:AbCd…произвольные байты

Дробных чисел нет. Цену в рублях и копейках хранят целым числом копеек — ровно так же, как суммы в самой сети.

Удаление — запись со значением null и без типа:

const tx = data({ data: [{ key: 'ball', value: null }], chainId: 'R' }, seed);
состояние до: [{"key":"ball",...},{"key":"dopusk",...},{"key":"gruppa",...}]
состояние после: [{"key":"dopusk","type":"boolean","value":true},{"key":"gruppa","type":"string","value":"IS-21"}]
Интересный факт

Удаление убирает ключ из текущего состояния, но не из истории: транзакция, которая его записывала, никуда из цепочки не делась. Блокчейн остаётся блокчейном — стереть прошлое нельзя, можно только перестать считать его текущим.

Отвечено вопросов: 0 из 3
Кому уходит транзакция данных?
Как удалить ключ?
Как хранить цену в рублях и копейках?
Отвечено верно: 0 из 3

Сколько это стоит и где границы​

ЧТО ОГРАНИЧЕНО И ПОЧЕМУ ЭТО ВАЖНОдлина ключадо 400 знаков401-й даёт «Too big sequence requested»размер значениядо 32 767 байт32 768 уже отвергаетсяключей в одной записисколько влезет100 штук прошли одной транзакциейцена0,001 WAVES за начатый КБ1000 байт — 0,001, 1100 байт — уже 0,002составной ключ вместо вложенности: «vklad_3M57BFmz…» вместо словаря внутри словаряперебрать ключи по началу строки узел умеет — это и заменяет вложенные структуры
Проверено на живом узле: где именно проходят границы

Цена растёт по килобайтам:

значение 10 байт → комиссия 100000
значение 1000 байт → комиссия 100000
значение 1100 байт → комиссия 200000
значение 2100 байт → комиссия 300000
значение 3100 байт → комиссия 400000

То есть 0,001 WAVES за каждый начатый килобайт. Первый килобайт стоит столько же, сколько десять байт, а вот 1100 байт — уже вдвое дороже.

Границы (проверено перебором):

ключ 400 знаков → код 200
ключ 401 знак → код 400 | Too big sequence requested
значение 32 767 байт → код 200
значение 32 768 байт → код 400 | Too big sequence requested
Совет

Сообщение Too big sequence requested одно на оба случая — и на длинный ключ, и на большое значение. Что именно велико, узел не уточняет, так что проверять придётся самому.

Одной транзакцией можно записать много ключей сразу — сто штук прошли без вопросов. Комиссию при этом надо ставить по размеру:

100 ключей с комиссией 100000 → State check failed. Reason: Fee for DataTransaction
(100000 in WAVES) does not exceed minimal value of 200000 WAVES.
100 ключей с комиссией 300000 → код 200

Как читать состояние​

Весь словарь целиком:

curl .../addresses/data/<адрес>

Один ключ:

curl .../addresses/data/<адрес>/n7
{"key":"n7","type":"integer","value":7}

Несуществующий ключ:

код: 404 | {"error":304,"message":"no data for this key"}

Ключи по образцу — то, что заменяет вложенные структуры:

curl '.../addresses/data/<адрес>?matches=n1%5B0-9%5D'
найдено: 10
[{"key":"n10","type":"integer","value":10},{"key":"n11",…},{"key":"n12",…}]
Нажми на часть выражения
Важно

Вложенных структур в состоянии нет. Вместо студенты[z-1].оценки пишут составной ключ: z_z-1_ball. А потом достают все ключи студента одним запросом по образцу. Этот приём встречается в каждом втором dApp.

Отвечено вопросов: 0 из 3
Сколько стоит запись значения в 1100 байт?
Что означает Too big sequence requested?
Чем заменяют вложенные структуры?
Отвечено верно: 0 из 3

Типичные ошибки​

Ошибка 1. Искать поле получателя.

Его нет. Записать в чужой словарь нельзя никаким способом — это не ограничение библиотеки, а правило сети.

Ошибка 2. Ставить комиссию по умолчанию на большую запись.

State check failed. Reason: Fee for DataTransaction (100000 in WAVES)
does not exceed minimal value of 200000 WAVES.

Библиотека считает комиссию по размеру сама, если её не задавать вручную. Задали — считайте сами.

Ошибка 3. Хранить дробное число.

Тип integer не примет 1.5. Хранить надо копейки или тысячные доли, а запятую ставить при показе.

Ошибка 4. Забыть закодировать образец в адресе.

?matches=n1[0-9] без кодирования доедет до узла искажённым, и ответ будет пустым — без всякой ошибки.

Ошибка 5. Складывать в состояние файлы.

Тип binary есть, но 32 767 байт — это потолок, и каждый килобайт платный. Файлы кладут в обычное хранилище, а в состояние — только их хеш.

Отвечено вопросов: 0 из 3
Запрос с matches вернул пустой список, хотя ключи есть. Первое, что проверить?
Как правильно хранить документ?
Почему узел отказал в записи ста ключей с обычной комиссией?
Отвечено верно: 0 из 3

Шпаргалка по главе​

Что нужноКак
Записатьdata({ data: [{ key, type, value }], chainId }, seed)
Удалить ключ{ key: 'ball', value: null } — без типа
Весь словарьGET /addresses/data/<адрес>
Один ключGET /addresses/data/<адрес>/<ключ> (404 = нет такого)
Ключи по образцуGET /addresses/data/<адрес>?matches=<регулярка в URL>
Типы значенийinteger, boolean, string, binary
Границыключ ≤ 400 знаков, значение ≤ 32 767 байт
Цена0,001 WAVES за каждый начатый килобайт

Словарь главы​

ТерминЧто это
Состояние аккаунтаСловарь «ключ — значение», свой у каждого адреса
Транзакция данныхТип 12; пишет только в словарь подписавшего
Составной ключПриём вместо вложенности: z_z-1_ball
matchesФильтр ключей по регулярному выражению
binaryТип для произвольных байтов; хранят хеши, а не файлы
Удаление ключаЗапись value: null без типа
Too big sequence requestedПревышена граница ключа или значения
Начатый килобайтЕдиница, по которой считают комиссию

Цель: скорость ≥ 95 зн/мин, точность ≥ 88%

const { data } = require('@waves/waves-transactions');

Что должен уметь после главы​

  • записать несколько значений в состояние своего аккаунта и прочитать их;
  • назвать четыре типа значений и объяснить, почему нет дробных чисел;
  • удалить ключ и объяснить, что при этом происходит с историей;
  • посчитать комиссию по размеру записи;
  • назвать границы ключа и значения и узнать соответствующее сообщение;
  • заменить вложенную структуру составным ключом и выборкой по образцу.

Проверка по главе​

Сводная проверка по всей главе: 10 вопросов, 5:00 на всё, без подсказок по ходу. Вопросы показываются по одному, ответ изменить нельзя. Если время выйдет — экзамен завершится с тем, что успел ответить. Пересдавать можно сколько угодно раз.

Куда дальше: проверенные ресурсы​

Видео по теме

ВидеоThe Ultimate Guide to Waves Blockchain: Revolutionizing dApps & Smart Contracts in 2023Bruno Invest
ВидеоWaves SDK, connecting blockchain to blockchain. (multilingual subtitles)Crypto Crave Dude
ВидеоWaves Platform Explained on Proof Of MakeProof
ВидеоWaves Explorer: user guideWaves Tech
ВидеоWaves: A global open-source platform for decentralized applications.Crypto Diamond

Комментарии

Обсуждение живёт в GitHub Discussions и грузится с чужого домена — поэтому только по нажатию.