Как устроен процесс голосования?

Как устроен процесс голосования?


Команда разработчиков ChronoBank рассказала, как мы уменьшаем требуемое количество газа для проведения голосования и создаем смарт-контракты для него.


Функционал ChronoMint предоставляет возможность организовывать голосования - необходимый инструмент для принятия стратегических решений в экосистеме ChronoBank. Голосование, организованное на блокчейне, должно отвечать следующим требованиям:

  • Безопасность
  • Надежность
  • Управление голосованием (создание, проведение голосования, окончание голосования)

Первым шагом к идеальной системе голосования было создание нескольких контрактов (мы называем их managers), которые взяли на себя всю работу с голосованиями и их управлением. Стоит отметить, что хранение данных в хранилищах для всех видов managers использует специальный контракт StorageManager.


📌 StorageManager может запретить или разрешить доступ к хранилищу.



Эти контракты обладают общим пространством для хранения данных и имеют доступ к общим переменным. С одной стороны, это позволяет разделить процесс голосования на несколько функциональных контрактов (получение информации, само голосование, управление данными голосования) и разбить массивный размер кода на более мелкие контракты, но, с другой стороны, из-за этого все контракты связаны между собой и поэтому в них трудно вносить изменения. Помимо вышеупомянутого недостатка, эта схема реализации требовала больших издержек за подачу голосов и предполагала хранение множества статистических данных. Это не то чего мы хотели бы от наших голосований: наоборот, мы хотим, чтобы пользователям было легко стать частью экосистемы и участвовать в ее жизни.


Когда мы говорим об издержках речь идет о цена газа совершения некоторых действий, которые были у нас в предыдущих версиях:


  • Создать голосование - 787111
  • Проголосовать - 411641
  • Завершить голосование - 482976
  • Удалить голосование - 95073


Как вы могли видеть, это довольно много газа и есть множества возможностей для улучшения ...


Поэтому мы решили использовать другой подход. Как и ранее, мы оставили один контракт (VotingsManager) для управления, создания голосований в системе и получения общей информации - он останется точкой входа для всех пользователей, которые захотят принять участие в голосовании.

Но вместо хранения опросов как набора свойств в общем хранилище, мы создаем новый контракт для каждого опроса.


📌 Этот шаг позволяет упростить контракты в соответствии с внутренней логикой каждого контракта

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

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

Благодаря обновлению Byzantium были добавлены очень удобные и полезные команды - _returndatasize_ и _returndatacopy_. Эти функции возвращают размер возвращаемых данных делегированной функции и сохраняют возвращенные данные. Теперь мы можем их применить - использовать их в нашем прокси-контракте и очистить его код от любых особенностей backend функций. После этого у нас будет контракт, который будет создаваться каждый раз, когда будет создано новое голосование, и потребуется немного газа для развертывания почти пустого контракта.


Количество газа, необходимое для некоторых действий:

  • Создать опрос -  849476
  • Проголосовать  — 159331
  • Закончить голосование  — 443473
  •  Удалить голосование — 56486


Как видите, в этом случае наши издержки по газу в три раза меньше, что экономит ресурсы экосистемы для наших пользователей.

Да, создание голосования в этом варианте требует чуть больше газа но все остальные издержки сокращаются. Окончание и удаление голосования теперь требует меньше газа.


Развертывание подсистемы для голосования (требуемое количество газа):

Первый вариант: 3089834 + 3789833 + 2891094 = 9,770,761

Второй вариант: 2440890 + 586243 + 3014376 = 6.041.509


Источник




Report Page