📢 Руководство для разработчиков: Система ресурсных кредитов

in #steem5 years ago (edited)

Привет, Steem-разработчики. Перед вами руководство, целью которого является демистификация системы распределения ресурсов и RC. Материал предназначен для разработчиков, имеющих дело с пользовательскими интерфейсами Steem, приложениями и библиотеками клиентов.

Бесструктурность как отсутствие фиксации состояния

Прежде всего, несколько слов о бесструктурности. Много усилий было потрачено на тщательное разделение структурных (зависящих от состояния) и неструктурных (не зависящих от состояния) вычислений. Это нужно для того, чтобы UI и клиентские библиотеки могли выполнять бесструктурные алгоритмы локально. Локальные вычисления всегда предпочтительнее RPC-API в плане производительности, стабильности, масштабируемости и безопасности.

К сожалению, в клиентской библиотеке отсутствует поддержка RC-алгоритмов. Данный туториал и сопутствующий ему скрипт призваны стать руководством для тех, кто обеспечивает работу UI и клиентских библиотек, объясняющим как добавить поддержку системы RC.

Демо-скрипт RC

Чтобы начать работу, я (theoretical) перевел некоторые ключевые алгоритмы с C++ на Python: https://github.com/steemit/rcdemo.
Например, какое количество ресурсов потребляет одна транзакция голосования? Скрипт rcdemo позволяет нам это выяснить:

>>> from rcdemo import *
>>> count = count_resources(vote_tx, vote_tx_size)
>>> count["resource_state_bytes"]
499232
>>> print(json.dumps(count))
{"resource_count": {"resource_history_bytes": 133, "resource_new_accounts": 0, "resource_market_bytes": 0, "resource_state_bytes": 499232, "resource_execution_time": 0}}

Функция count_resources() является бесструктурной. Это означает, что вся необходимая для расчета информация содержится в самой транзакции. Она не зависит от того, что происходит в блокчейне, равно как и от действий других пользователей. [1] [2] [3]

[1] Хотя не исключено, что в будущих версиях steemd вычисления будут изменены, например для того, чтобы исправить баг, из-за которого время выполнения всегда указывается равным нулю.

[2] Для удобства некоторые константы, используемые в вычислении, предоставляются элементом size_info из rc_api.get_resource_params(). Только обновление версии steemd может изменить какие-либо значения, возвращаемые rc_api.get_resource_params(), поэтому, вероятно, можно запросить этот API один раз, во время запуска или при первой необходимости, а затем навсегда кэшировать результат. Или даже вставить результат rc_api.get_resource_params() в исходный код библиотеки или приложения.

[3] rcdemo.py также требует от вас ввести размер транзакции в count_resources(). Это происходит по причине того, что rcdemo.py был создан в качестве автономного скрипта, не зависящего от какой-либо отдельно взятой клиентской библиотеки. В случае интегририрования rcdemo.py в клиентскую библиотеку вы можете использовать сериализатор библиотеки для автоматического вычисления размера транзакции, так чтобы вызывающий count_resources() не должен был его указывать.

Ресурсы

Рассмотрим различные виды ресурсов, ограничиваемых системой RC.

  • resource_history_bytes : количество байтов, занимаемых транзакцией.
  • resource_new_accounts : количество аккаунтов, созданных транзакцией.
  • resource_market_bytes : количество байтов, используемых транзакцией, если она содержит рыночные операции.
  • resource_state_bytes : количество байтов состояния цепи, необходимое для поддержки транзакции.
  • resource_execution_time : оценка количества времени, необходимого для выполнения транзакции. В данный момент составляет ноль в связи с проблемой 2972.

Ресурсы имеют разные масштабы. Ресурсы используют арифметику с фиксированной точкой, где один "штрих" значения ресурса является "дробным" значением ресурса. Сейчас масштабы ресурсов разбросаны по разным местам. Результат count_resources() имеет следующий масштаб:

  • resource_history_bytes : один байт равен 1.
  • resource_new_accounts : один аккаунт равен 1.
  • resource_market_bytes : один байт равен 1.
  • resource_state_bytes : один байт, который должен храниться вечно, равен константе времени компиляции steemd STATE_BYTES_SCALE, т.е. 10000. Байты, которые должны храниться в течение ограниченного периода времени, имеют значение меньше 10000, в зависимости от того, как долго они должны храниться. Конкретные константы, используемые в различных случаях, указываются в полях resource_params["size_info"]["resource_state_bytes"].
  • resource_execution_time : одна наносекунда процессорного времени равна 1. Значения основаны на экспериментальных измерениях, выполненных машиной, похожей на серверы steemit.com. Было выполнено некоторое округление и корректировка времени выполнения нескольких операций в целях учета дополнительной обработки вызванных ими виртуальных операций.

Уровни пула ресурсов

Каждый ресурс имеет глобальный пул, который представляет собой количество оставшихся ресурсов. Код пула поддерживает дробные ресурсы, знаменатель представлен параметром resource_unit. Так, например, если resource_params["resource_params"]["resource_market_bytes"]["resource_dynamics_params"]["resource_unit"] это 10, то уровень пула 15,000,000,000 в действительности представляет 1,500,000,000 байт.

Ресурсные кредиты

Стоимость RC для каждого ресурса зависит от следующей информации:

  • Количество ресурсов в соответствующем пуле ресурсов
  • Глобальная скорость регенерации RC, которая может быть вычислена как total_vesting_shares / (STEEM_RC_REGEN_TIME / STEEM_BLOCK_INTERVAL)
  • Параметры кривой цены в соответствующем объекте price_curve_params

Для удобства rcdemo.py содержит класс RCModel, на полях которого размещается вся эта информация.

>>> print(json.dumps(model.get_transaction_rc_cost( vote_tx, vote_tx_size )))
{"usage": {"resource_count": {"resource_history_bytes": 133, "resource_new_accounts": 0, "resource_market_bytes": 0, "resource_state_bytes": 499232, "resource_execution_time": 0}}, "cost": {"resource_history_bytes": 42136181, "resource_new_accounts": 0, "resource_market_bytes": 0, "resource_state_bytes": 238436287, "resource_execution_time": 0}}
>>> sum(model.get_transaction_rc_cost( vote_tx, vote_tx_size )["cost"].values())
280572468

Объект model, созданный в rcdemo.py, является экземпляром RCModel, использующим зафиксированные в коде значения для уровней своего пула и оценки глобальной скорости восстановления RC. Эти значения были взяты из рабочей сети и зафиксированы в исходном коде rcdemo.py в конце сентября 2018 года. Таким образом, расчет стоимости RC, производимый rcdemo.py по умолчанию, является правильным по состоянию на сентябрь 2018 года, однако станет менее точным по мере того, как "живые" значения отклоняются от фиксированных значений. При интеграции кода rcdemo.py в приложение, клиентскую библиотеку или при любой другой ситуации, в которой возможен RPC-доступ, вам следует понять, каким именно образом код будет запрашивать текущие значения у конечной точки RPC steemd. (Некоторые библиотеки с большей вероятностью предпочтут сделать RPC автоматически, другие библиотеки могут захотеть оставить эту работу на совести пользовательского кода).

Ограничения транзакции

Предположим, что Steem Power аккаунта равна 15. Сколько раз он может проголосовать?

>>> vote_cost = sum(model.get_transaction_rc_cost( vote_tx, vote_tx_size )["cost"].values())
>>> vote_cost
280572468
>>> vote_cost * total_vesting_fund_steem / total_vesting_shares
138.88697555075086

Это количество Steem Power (в сатоши), которое потребуется аккаунту для выполнения транзакций один раз в течение 5 дней (STEEM_RC_REGEN_TIME).

Наш аккаунт с 15 SP располагает 15000 SP-сатоши, таким образом он способен произвести 15000 / 138, или около 108 таких транзакций на протяжении 5 дней.

Вы можете рассматривать число 138 (или 0.138) как "стоимость" "стандартизированной" транзакции голосования. Она играет роль, аналогичную комиссии за транзакцию в Bitcoin, при этом являясь не совсем комиссией. Потому что слово "комиссия" подразумевает отказ от постоянного токена с ограниченным и контролируемым уровнем эмиссии. Именно количество SP обеспечит пользователю дополнительную возможность голосовать каждые 5 дней (но это количество может быть немного больше или меньше, если ваши транзакции голосования используют слегка различное количество ресурсов).

Интеграция демо-скрипта

Скрипт rcdemo.py – это автономный скрипт на Python без зависимостей, без доступа к сети и без сериализатора транзакций. Это порт алгоритмов и несколько примеров транзакций для ознакомительных целей.

В конечном счете сопровождающие стороны клиентской библиотеки должны интегрировать rcdemo.py или эквивалентный функционал в каждую клиентскую библиотеку Steem. Такая интеграция зависит от идиом и ограничений каждой конкретной клиентской библиотеки, например:

  • Клиентская библиотека с простой философией "явное лучше тайного" может просто переименовать rcdemo,
    удалить пример кода, добавить немного связующего кода и предоставить его клиентам практически как есть.
  • Клиентская библиотека с автомагической философией "невидимого RPC", способного обеспечить транзакцию, внести существенные изменения в rcdemo или отобразить интерфейс, как get_rc_cost(tx), который будет возвращать стоимость RC транзакции. Поскольку стоимость RC зависит от состояния чейна, данная функция get_rc_cost() будет вызывать RPC steemd (или использовать кэшированные значения) для получения дополнительных входных данных, необходимых алгоритмам без отслеживания состояния, таким как пулы ресурсов, total_vesting_shares и т.д.
  • Клиентская библиотека, которая имеет общую политику фиксированных в коде констант из исходного C++ кода steemd , может дистрибутировать rc_api.get_resource_parameters() как часть исходного кода, поскольку результаты rc_api.get_resource_parameters() могут измениться только в новой версии steemd. (Возможно, подобного рода вещи каким-то образом автоматизированы в сборочных скриптах библиотеки).
  • Если те, кто поддерживает работу клиентской библиотеки, не хотят обязывать себя делать новые релизы каждый раз, когда меняются значения в steemd, вместо этого они могут выбрать вызов rc_api.get_resource_parameters(). Повышение производительности и уровня безопасности в обмен на удобство отправки запросов steemd для сообщения этих значений.
  • Клиентская библиотека с собственным классом Transaction может реализовать методы класса вместо автономных функций.
  • Клиентская библиотека на JavaScript, Ruby или Go может перевести алгоритмы в rcdemo.py на другой язык.

Как видите, интеграция поддержки системы RC в клиентскую библиотеку Steem предполагает ряд архитектурных и технических решений.

Надеюсь, что это руководство помогло вам лучше понять, как работают ресурсы и RC. Если есть что-то еще, что вы хотели бы знать о системе RC, пожалуйста, оставьте комментарий под оригинальным постом.


Переведено @blockchained

Оригинал поста: ЗДЕСЬ


Если вам нравится то, что мы делаем - поддержите делегата blockchained в сети Steem


Телеграм чат: https://t.me/steemit


Вы можете торговать токенами STEEM/SBD на RuDEX с 0% торговой комиссией

Coin Marketplace

STEEM 0.31
TRX 0.12
JST 0.033
BTC 64605.91
ETH 3159.61
USDT 1.00
SBD 4.11