После вчерашней остановки блокчейна Голос я сидел и изучал код перед сном, рассматривая варианты разных ошибок. И меня осенило. В визе есть тоже баг, который необходимо исправить в ХардФорке. Проблема заключается в маленьком ньюансе при осуществлении начислении SHARES. А именно в методе create_vesting.
Раньше все SHARES аккаунта (не эффективные, а именно хранимые в аккаунте без учета делегирования) просто начислялись избранным делегатам в votes. После последнего хардфорка происходит деление SHARES на количество избранных пользователем делегатов.
Когда происходит create_vesting (а это происходит довольно часто, в том числе при операции award) вызывается метод adjust_proxied_witness_votes https://github.com/VIZ-World/viz-world/blob/master/libraries/chain/database.cpp#L1285
И далее рекурсивно происходит увеличение votes у каждого делегата (adjust_witness_votes), за которого проголосовал аккаунт.
https://github.com/VIZ-World/viz-world/blob/master/libraries/chain/database.cpp#L1677
https://github.com/VIZ-World/viz-world/blob/master/libraries/chain/database.cpp#L1696
https://github.com/VIZ-World/viz-world/blob/master/libraries/chain/database.cpp#L1704
И, наконец, увеличение votes: https://github.com/VIZ-World/viz-world/blob/master/libraries/chain/database.cpp#L1717
Так как у нас теперь vote делится на witnesses_voted_for https://github.com/VIZ-World/viz-world/blob/mainnet-dev/libraries/chain/include/graphene/chain/account_object.hpp#L89
То у нас может возникнуть ошибка, когда за аккаунт, который не получал других голосов начисляют разделяемый голос. После чего голосующий получит SHARES, например, за award.
После снятия голоса делегат будет иметь vote равный ошибке. А именно начисленный SHARES минус начисленный SHARES деленный на количество голосов. Данная ошибка не критичная, но ее надо исправить для равных расчетов. И возникает вопрос, как именно ее исправить.
Опираться на witness_vote_fair_weight нельзя, так как при делении delta за create_vesting на количество голосов может сохраниться остаток, в виде 0.000001 SHARES. После того как число таких остатков превысит по количеству число голосов аккаунта за делегатов, мы можем получить ситуацию, что при снятии голосов отнимется больше, чем будет даваться. Правильным решением будет ввод дополнительной переменный для account_object.
witnesses_vote_weight
Который можно будет использовать для сохранения числа vote для одного делегата (или его модификации delta деленный на witnesses_voted_for), а также вычитать его при снятии голоса.
С сегодняшнего дня я займусь пересчетом всей системы и стабилизации ее, чтобы не было ошибок.
Наградить автора поста