Пропускная способность
Блокчейн Голос является системой с нулевыми комиссиями за транзакции. Однако, объём информации, который можно записать в блокчейн в единицу времени, не бескон ечен. Для контроля над расходованием общей пропускной способности был разработан специальный механизм её распределения.
Максимально доступная bandwidth аккаунта в системе напрямую зависит от количества Силы Голоса (vesting shares).
У аккаунта в системе существует 3 ограничителя пропускной способности:
- 1.forum bandwidth: ограничивает объём операций постинга постов и комментариев, апвоутов.
- 2.market bandwidth: ограничивает объём операций трансфера монет и выставления/отмены рыночных ордеров на внутренней бирже.
- 3.post bandwidth: штрафует аккаунт уменьшением выплаты за пост, если аккаунт постит слишком много постов.
При превышении данного типа bandwidth возникает ошибка: Account exceeded maximum allowed bandwidth per vesting share.
Данные типы bandwidth по сути являются единой сущностью. Отличие в том, что market bandwidth представляет собой 1/10 от общей bandwidth аккаунта. Например, пусть bandwidth аккаунта - 100 KB. Тогда:
- forum bandwidth: 100 KB
- market bandwidth: 10 KB
Время восстановления bandwidth от 0 до 100% определяется константой
STEEMIT_BANDWIDTH_AVERAGE_WINDOW_SECONDS
и составляет 7 дней (актуально для 0.17.0).В исходных текстах происходит в database.cpp в
bool database::update_account_bandwidth
.При получении транзакции аккаунта нода golosd проверяет, не превысил ли аккаунт отведённую ему полосу пропускания. Это происходит по следующей формуле:
has_bandwidth = (account_vshares * max_virtual_bandwidth) > (account_average_bandwidth * total_vshares)
has_bandwidth
: результат сравнения, получается True если есть доступная полоса, и False если нетaccount_vshares
- Сила Голоса аккаунта в виде vesting sharesmax_virtual_bandwidth
- максимальная виртуальная пропускная способность сети.account_average_bandwidth
- показатель использования аккаунтом своей полосыtotal_vshares
- суммарное значение vesting shares всех аккаунтов в блокчейне
Если вышеуказанную формулу записать как
(account_vshares * max_virtual_bandwidth) / (account_average_bandwidth * total_vshares)
, то получится число, показывающее долю использования аккаунтом своей полосы.В данной формуле все переменные являются легко доступными параметрами, кроме
account_average_bandwidth
. Для получения данного значения требуется провести ряд вычислений.- 1.С помощью API-метода
get_account_bandwidth
можно получить значение bandwidth на момент последней совершённой транзакции. Данное значение не будет актуальным на текущий момент времени, так как bandwidth всё время восстанавливается (уменьшается % потраченной пропускной способности). Note: это же значение bandwidth можно получить с помощью API-вызоваget_accounts
, однако в этом случае bandwidth будет находиться в поле'new_average_bandwidth'
(а поле'average_bandwidth'
следует проигнорировать, так как оно относится к устаревшему механизму контроля bandwidth и является deprecated). - 2.В результатах вышеупомянутого вызова так же присутствует поле
"last_bandwidth_update"
, оно показывает момент последнего обновления bandwidth. - 3.Если с момента последнего обновления прошло больше времени чем
STEEMIT_BANDWIDTH_AVERAGE_WINDOW_SECONDS
, тоaccount_average_bandwidth
автоматически становится 0, это означает, что аккаунт может воспользоваться всей своей доступной полосой пропускания. - 4.Если же времени прошло меньше, то следует подсчитать, на сколько восстановилась bandwidth. Для этого применяется следующая формула:
new_bandwidth = ((STEEMIT_BANDWIDTH_AVERAGE_WINDOW_SECONDS - elapsed_time) * account_average_bandwidth) / STEEMIT_BANDWIDTH_AVERAGE_WINDOW_SECONDS
, гдеelapsed_time
- сколько прошло времени с момента последнего обновления bandwidthaccount_average_bandwidth
- значение bandwidth на момент последнего обновления
- 5.Теперь у golosd есть данные о текущем состоянии bandwidth аккаунта, но теперь ему так же нужно определить, можно ли разрешить аккаунту совершить транзакцию. Для этого golosd подсчитывает, как изменится bandwidth после принятия транзакции, и не будет ли при этом превышена полоса пропускания. Для этого вычисляется bandwidth транзакции:
trx_bandwidth = trx_size * STEEMIT_BANDWIDTH_PRECISION
, гдеtrx_size
- размер транзакции в байтах. Для market-операций этот размер дополнительно умножается на 10, из-за чего и происходит то, что для market операций доступная bandwidth в 10 раз меньше чем для forumSTEEMIT_BANDWIDTH_PRECISION
- константа, определяющая точность вычислений при работе с bandwidth
- 6.Вычисляется финальное значение
account_average_bandwidth = new_bandwidth + trx_bandwidth
Мы можем самостоятельно вычислять максимально доступную bandwidth аккаунта и потреблённую на текущий момент.
Для получения значения потреблённой полосы, получается формула следующего вида:
used_kb = account_average_bandwidth / STEEMIT_BANDWIDTH_PRECISION / 1024
Для получения максимально доступной аккаунту полосы получается следующая формула. Какую долю от суммарной СГ имеет аккаунт, такую долю он и может взять из общей
max_virtual_bandwidth
:avail_kb = account_vshares/total_vesting_shares * max_virtual_bandwidth / STEEMIT_BANDWIDTH_PRECISION / 1024
Практическую реализацию вычисления bandwidth вы можете посмотреть в функции
get_bandwidth
в functions.py, которая используется в скрипте get_bandwidth.py.При общей высокой загруженности сети срабатывает механизм ограничения общей пропускной способности через снижение
max_virtual_bandwidth
.В исходных текстах механизм реализован в database.cpp в функции
void database::update_global_dynamic_data()
и работает по следующему алгоритму:- 1.Примерно раз в минуту (каждые 20 блоков) происходит пересчёт
max_virtual_bandwidth
. Первым делом проверяется, не превышает ли средний размер блока (average_block_size
) 1/4 от максимального размера блока (maximum_block_size
).- 1.Если превышает, то
current_reserve_ratio
уменьшается в 2 раза, что по сути приводит к уменьшениюmax_virtual_bandwidth
так же в 2 раза. - 2.Если не превышает, и ранее
current_reserve_ratio
был ограничен, то происходит линейный рост этого показателя путём инкремента на 1 единицу.
Таким образом, ограничение общей пропускной способности активируется, когда средний размер блока становится более 25% от текущего максимально размера блока. При этом ограничение срабатывает достаточно резко, т.к.
max_virtual_bandwidth
падает сразу в 2 раза. При этом, недостаток bandwidth сразу же могут испытать те пользователи, которые имеют потребление полосы выше 50%. Восстановление же общей доступной полосы после включения ограничения происходит плавно, в течение 3-4 дней.Является самостоятельным ограничителем и никак не связана с пропускной способностью сети. Предназначение - штрафовать аккаунт, который постит слишком часто.
Реализация в исходных текстах находится в steem_evaluator.cpp в
void comment_evaluator::do_apply()
Last modified 3yr ago