Привет народ ! ✋🏻😎
Вообще эта статья планировалась быть опубликованной на Хабре, ориентируясь на соответствующую аудиторию. Люди там в основном с IT - направленностью и для их понимания показаны кусочки кода с описанием происходящих процессов, и даны ссылки на исходники.
Я пытался несколько раз всё тоже самое описать только словами, где-то подробнее, где-то не очень, и хорошо, что я этим занимался, потому что по ходу редактирования я нашёл свои ошибки, которые нужно было исправлять в изначальной версии.
Спустя некоторое время мне вспомнилось начало одной песни, я его немного изменил:
несколько дней назад я написал эту статью, но с Хабровским темпом модерации, я устал тексты переделывать, так что пусть в этой статье всё остаётся, как было
В конце концов, если кому-то что-то будет не понятно - вы всегда можете уточнить это в чатах 😉
Все слышали про Халвинг?
Насколько я понимаю, Халвинг происходит от слова half (половина), соответственно halving - уполовинивание или деление на два
Сразу попрошу тех, кому многие вещи покажутся избыточно-очевидными, не кидаться сильно камнями 🙏
Данный материал будет использоваться в совокупности с другим материалом, как один из элементов обучения новичков, в том числе тех, кто совсем не знаком с языками программирования, по этому статья может показаться не полной. Извиняйте 🙏 если глаза начнёт резать
Когда в какой-либо криптовалюте происходит Халвинг, сообщество ожидает снижения будущего количества генерируемых монет, а соответственно потенциального сокращения предложения этих монет на рынках, следовательно повышения рыночной стоимости
По сути Халвинг - это программное создание дефицита криптовалюты. Для криптовалюты с ограниченной эмиссией это событие существенно влияющее на дальнейшую работу всей сети. Мы как раз рассмотрим две такие криптовалюты, а точнее, как реализован в них Халвинг
В глобальном понимании, Халвинг необходим для контроля инфляции общего количества выпущенных монет и это очень важная составляющая и неотъемлемая часть экономической модели многих криптовалют и, конечно в Prizm есть свой Халвинг и имя ему – PARATAX. Но начнём мы с Bitcoin
Bitcon
В блокчейне Bitcoin реализация Халвинга точно соответствует смыслу этого слова – по прошествии 210 000 блоков (примерно 4 года) максимально возможная награда для майнеров за один блок становится на 50% меньше:
50 btc -> 25 btc -> 12,5 btc -> 6,25 btc -> 3,125 btc.. и т.д.
Вычисление происходит в соответствии с высотой текущего блока, она делится на интервал (nSubsidvHalvingInterval), значение которого установлено на 210 000
Определение возможного количества генерируемых монет описано в методе GetBlockSubsidy()
Если результат деления (halvings) больше или равен 64, то вознаграждение будет равным нулю, то есть когда высота текущего блока достигнет 64 × 210 000, майнеры перестанут генерировать новые биткоины и продолжат собирать только комиссии с транзакций
С учётом того, что блокчейн Bitcoin стремится к интервалу в 10 минут между генерацией блоков, то момент добычи последнего биткоина вероятно будут наблюдать наши правнуки
После проверки halvings, вычисляется количество монет, которое майнер в дальнейшем будет использовать для их генерации. Делается это путём побитового сдвига вправо
nSubsidy >>= halvings;
Поскольку результат деления записывается в целочисленную переменную (int halvings), дробная часть результата просто отбрасывается и побитовый сдвиг всегда происходит на целое число разрядов. А сдвиг на один разряд двоичного представления положительного числа - это фактически деление этого числа на 2
PRIZM
PARATAX вводился постепенно и первый его элемент был введён в действие на высоте 571800 с появлением PrizmCore версии1.9.19 (09.08.2019г.). У владельцев PrizmCore в интерфейсе сразу появилось окошко, отображающее 3.73% что соответствовало проценту текущей эмиссии от максимальной.
С этого момента Paramining для каждого аккаунта, в момент его генерации становился меньше на значение этого процента, но в расчёте участвует только целое значение процента, его дробная часть отбрасывается, как в случае с Bitcoin, по тем же причинам - результат присваивается в целочисленную переменную.
Поскольку эмиссия новых монет в PRIZM это не прерогатива форжеров, а динамическая и индивидуальная величина, почти для каждого владельца монет, то и реализация Халвинга разработчиками сделана с учётом индивидуальных характеристик каждого аккаунта
После появления PrizmCore версии 1.10.3, на высоте 888888 (19.02.2020г.) процент текущей эмиссии в расчётах количества генерируемых монет, увеличивается в 2 раза.
PARATAX стал больше походить на Халвинг, а Paramining стал вычисляться по сложному проценту. Но не всё так буквально, давайте разбираться.
метод устанавливающий PARATAX:
Сколько генерируется монет ?
Как уже было сказано, в PRIZM динамическая и индивидуальная генерация новых монет. Это означает, что для каждого аккаунта, кому сейчас должны генерироваться монеты, вначале нужно рассчитать индивидуальный PARATAX
- Вычисляем Paramining с учётом обычного PARATAX
Шаг 1. Вызываем метод установки PARATAX. Передаём в метод высоту = 0
Поскольку 0 меньше 888888, PARATAX устанавливается, как простой процент текущей эмиссии, но только целая его часть.
Шаг 2. Далее вызываем метод calculateOrdinaryInterest(), где вычисляется количество монет с учётом количества прошедших 86400 сек (суток), уменьшенное на, установленный в предыдущем шаге процент PARATAX
- Шаг 3. Результат присваивается в переменную ordinaryPayout
- Вычисляем Paramining по сложному проценту с учётом двойного PARATAX
Шаг 1. Вызываем метод установки PARATAX. Передаём в метод высоту = 888888, PARATAX устанавливается в зависимости от Холд-статуса аккаунта, для которого идёт вычисление и корректируется на 97% или 98% соответственно, если результат умножения обычного PARATAX на 2, превышает эти константы.
Шаг 2. Далее вызываем метод calculateCompoundInterestInternal(), где вычисляется количество монет с учётом количества периодов по 50 секунд за прошедшее время, уменьшенное на процент PARATAX который уже установлен в двойном размере и скорректирован.
небольшое отступление про "скачки":
Когда текущая эмиссия повышается на 1%, метод getParataxPercent() возвращает процент текущей эмиссии без дробной части.
Например текущая эмиссия = 1 234 567 891 pzm
1 234 567 891 * 100 / 6 000 000 000 = 20,5761315167 %
Возвращаемое значение будет = 20
Далее возвращаемое значение умножается на 2, в нашем примере long percent = 40
То есть при обычном Paramining = 100 pzm, результатом вычислений будет:
100 - 40% = 60 pzm (6000 неделимых копеек)
Когда текущая эмиссия достигнет 21%, в переменную percent будет присвоено значение 42
Соответственно, результатом будет:
100 - 42% = 58 pzm
Разница не очень заметна. Но чем выше текущая эмиссия, тем сильнее ощущается разница
Посмотрим на последние "скачки":
Текущая эмиссия достигнет 46%
В переменную percent присваивается значение 92
Результат: 100 - 92% = 8 pzm
Текущая эмиссия достигнет 47%
В переменную percent присваивается значение 94
Результат: 100 - 94% = 6 pzm
Разница между 8 и 6 = 25%, то есть Paramining для каждого аккаунта пересчитался на 25% в меньшую сторону
Текущая эмиссия достигнет 48%
В переменную percent присваивается значение 96
Результат: 100 - 96% = 4 pzm
Разница между 6 и 4 = 33,3(3)%, то есть Paramining для каждого аккаунта пересчитался на 33% в меньшую сторону
Текущая эмиссия достигнет 49%
В переменную percent присваивается значение 98
Результат: 100 - 98% = 2 pzm
Разница между 4 и 2 = 50%, то есть Paramining для каждого аккаунта пересчитался на 50% в меньшую сторону.
Ну прямо Халвинг какой-то 😁
Из этого следует, что когда текущая эмиссия достигнет 50%, в переменную percent будет присвоено значение 100
Спокойно ✋ всё в порядке, Paramining не исчезнет, в дело вступает константа 98%
Когда текущая эмиссия достигнет 50%, двойной PARATAX, учитываемый после вычисления Paramining по сложному проценту, будет оставаться прежним, изменения будут только в рамках Холд-статуса. Но PARATAX обычный будет продолжать увеличиваться вслед за эмиссией
Но и тот и другой Paramining всё равно будут зависеть от текущей эмиссии, об этом ниже в статье
И так, возвращаемся к нашему порядку
- ordinaryPayout
- Шаг 3. Результат присваивается в переменную compoundPayout
- Два полученных результата сравниваются и выбирается всегда тот, что меньше:
"красная зона"
Дело в том, что в официальном веб инструменте ParaMining calculator от разработчиков PRIZM (ссылка есть на GitHub prizm.space) то самое место, тот самый день и все последующие за ним дни, где Paramining рассчитанный по сложному проценту с двойным PARATAX начинает превышать обычный Paramining с простым PARATAX, - окрашиваются в красный цвет
Также в официальном веб инструменте TOOL visualizer от разработчиков PRIZM, шкала по которой движется стрелка отображающая текущий Paramining аккаунта, разукрашена в радужный градиент. Это создаёт визуальный эффект набора скорости Paramining. И та часть, где эта скорость становится максимальной - окрашена в красный цвет
Возвращаемся к порядку
- ordinaryPayout
- compoundPayout
- if (ordinaryPayout < compoundPayout)
- После того, как выбрано меньшее из двух расчётов количество монет, оно уменьшается ещё 😱 в методе decreaseAmountByGenesis()
Выбранное наименьшее количество монет уменьшается на коэффициент остатка эмиссии. Коэффициент никогда не превышает единицы (1), 1 - это 100% эмиссии.
Например:
Если текущая эмиссия = 49%, то коэффициент = 1 - 0,49 = 0,51
Но в данном случае, в значении текущей эмиссии учитывается дробная часть, поэтому например:
Если текущая эмиссия = 49,56%, то коэффициент = 1 - 0,4956 = 0,5044
Таким образом количество монет умножается на полученный коэффициент и вот здесь, в результате остаётся только целое значение, дробная часть отбрасывается, то есть результат умножения округляется в меньшую сторону (кому как удобнее для понимания)
Ещё примеры:
Когда текущая эмиссия достигнет 55%, коэффициент будет = 1 - 0,55
Количество монет умножится на 0,45
Когда текущая эмиссия достигнет 61,234%, коэффициент будет = 1 - 0,61234
Количество монет умножится на 0,38766
Ну я думаю, как вычисляется коэффициент остатка эмиссии должно быть предельно понятно. Но совсем не очевидным является то, что те самые "скачки" о которых говорилось выше, разбавляются ещё и изменением целого значения результата, после умножения вычисленного динамического коэффициента остатка эмиссии на выбранное наименьшее количество монет. То есть, итоговое генерируемое количество монет изменяется динамически в рамках одного и того же процента PARATAX.
Про "скачки" более детально:
Давайте снова прогуляемся по тем же примерам с эмиссией, но теперь мы будем учитывать крайние, пороговые значения текущей эмиссии и коэффициент её остатка. Для этого нам понадобится увеличить наш условный обычный Paramining, потому что 100 pzm для примера уже кажутся слишком малым значением 🙂
Итак, представим, что обычный Paramining без учёта PARATAX за какой-то отрезок времени составил 1000 pzm, тогда если:
Текущая эмиссия достигнет 46,99%
PARATAX умноженный на 2 = 92
1000 - 92% = 80 (8000 неделимых копеек)
Коэффициент = 1 - 0,4699 = 0,5301
8000 * 0,5301 = 4240 неделимых копеек
Генерируется монет = 42,4 pzm
Текущая эмиссия достигнет 47%
PARATAX умноженный на 2 = 94
1000 - 94% = 60
Коэффициент = 1 - 0,47 = 0,53
6000 * 0,53 = 3180
Генерируется монет = 31,8 pzm
Разница между 42,4 pzm и 31,8 pzm = 25 %
Текущая эмиссия достигнет 47,99%
PARATAX умноженный на 2 = 94
1000 - 94% = 60
Коэффициент = 1 - 0,4799 = 0,5201
6000 * 0,5201 = 3120
Генерируется монет = 31,2 pzm
Текущая эмиссия достигнет 48%
PARATAX умноженный на 2 = 96
1000 - 96% = 40
Коэффициент = 1 - 0,48 = 0,52
4000 * 0,52 = 2080
Генерируется монет = 20,8 pzm
Разница между 31,2 pzm и 20,8 pzm = 33,3(3) %
Текущая эмиссия достигнет 48,99%
PARATAX умноженный на 2 = 96
1000 - 96% = 40
Коэффициент = 1 - 0,4899 = 0,5101
4000 * 0,5101 = 2040
Генерируется монет = 20,4 pzm
Текущая эмиссия достигнет 49%
PARATAX умноженный на 2 с этого момента всегда = 98 (97 если есть Холд-статус)
1000 - 98% = 20
1000 - 97% = 30 (Холд-статус)
Коэффициент = 1 - 0,49 = 0,51
2000 * 0,51 = 1020
3000 * 0,51 = 1530 (Холд-статус)
Генерируется монет = 10,2 pzm или 15,3 pzm
Разница между 20,4 pzm и 10,2 pzm = 50 %
Разница между 20,4 pzm и 15,3 pzm = 25 % (Холд-статус)
Текущая эмиссия достигнет 49,99%
1000 - 98% = 20
1000 - 97% = 30 (Холд-статус)
Коэффициент = 1 - 0,4999 = 0,5001
2000 * 0,5001= 1000
3000 * 0,5001= 1500 (Холд-статус)
Генерируется монет = 10 pzm или 15 pzm
Текущая эмиссия достигнет 50%
1000 - 98% = 20
1000 - 97% = 30 (Холд-статус)
Коэффициент = 1 - 0,5 = 0,5
2000 * 0,5 = 1000
3000 * 0,5 = 1500 (Холд-статус)
Генерируется монет = 10 pzm или 15 pzm
Разницы никакой, то есть на 3 млрд эмиссии "скачка" не будет !
Из этого следует, что дальнейшее увеличение эмиссии будет динамически плавно корректировать количество генерируемых монет
Текущая эмиссия достигнет 50,99%
1000 - 98% = 20
1000 - 97% = 30 (Холд-статус)
Коэффициент = 1 - 0,5099 = 0,4901
2000 * 0,4901 = 980
3000 * 0,4901 = 1470 (Холд-статус)
Генерируется монет = 9,8 pzm или 14,7 pzm
Текущая эмиссия достигнет 51%
1000 - 98% = 20
1000 - 97% = 30 (Холд-статус)
Коэффициент = 1 - 0,51 = 0,49
2000 * 0,49 = 980
3000 * 0,49 = 1470 (Холд-статус)
Генерируется монет = 9,8 pzm или 14,7 pzm
Разницы нет
Текущая эмиссия достигнет 51,99%
1000 - 98% = 20
1000 - 97% = 30 (Холд-статус)
Коэффициент = 1 - 0,5199 = 0,4801
2000 * 0,4801 = 960
3000 * 0,4801 = 1440 (Холд-статус)
Генерируется монет = 9,6 pzm или 14,4 pzm
Текущая эмиссия достигнет 52%
1000 - 98% = 20
1000 - 97% = 30 (Холд-статус)
Коэффициент = 1 - 0,52 = 0,48
2000 * 0,48 = 960
3000 * 0,48 = 1440 (Холд-статус)
Генерируется монет = 9,6 pzm или 14,4 pzm
Разницы нет
Я надеюсь эти постепенные шаги более понятно обрисовывают ситуацию со "скачками" и генерацией монет в целом.
Если я не ошибся и в моём калькуляторе никто не просверлил дырочку, то получается что мы постепенно дойдём вот до таких значений:
точнее не мы, а..
Вы уже задумались, чьи правнуки доживут до этого времени ?
Текущая эмиссия достигнет 98,99%
1000 - 98% = 20
1000 - 97% = 30 (Холд-статус)
Коэффициент = 1 - 0,9899 = 0,0101
2000 * 0,0101 = 20
3000 * 0,0101 = 30 (Холд-статус)
Генерируется монет = 0,2 pzm или 0,3 pzm
Вы можете помочь правнукам подсчитать дальнейшую условную генерацию, но тогда нужно будет брать за основу ещё больший обычный Paramining без учёта PARATAX. Меньше 0,01 pzm (1 неделимой копейки) генерироваться не будет, в целочисленной переменной попросту будет оставаться 0 (ноль)
Возвращаемся к порядку
- ordinaryPayout
- compoundPayout
- if (ordinaryPayout < compoundPayout)
- Ну и в завершении, наше уменьшенное количество монет корректируется, если это нужно, следующим образом:
Значение константы MAX_BALANCE_AFTER_PARAMINING_PAYOUT_NQT приведено в начале статьи, где видно, что оно установлено как 100 млн.
Это 100 млн неделимых частей - копеек pzm, что соответствует 1 млн pzm.
Если наше уменьшенное количество монет прибавить к текущему балансу и в результате баланс будет больше 1 млн pzm, то наше уменьшенное количество монет корректируется на = 1 000 000 - текущий баланс.
Таким образом итоговое индивидуальное количество генерируемых монет не может поднять баланс аккаунта, для которого оно генерируется, больше 1 000 000 pzm.
P.s. На момент написания статьи, эмиссия PRIZM плавно подбирается к 50% 😉