Пособие по разработке программы для децентрализованного голосования Ethereum

1656665197 posobie po razrabotke programmy dlya deczentralizovannogo golosovaniya ethereum

Тимоти Ко

1*cQl1eHoplkcQF2dTaWo5FA
Фото Андре Франсуа

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

CryptoKitties, известный своей перегруженностью блокчейна Ethereum, является отличным примером dApp, уникальным образом сочетая концепцию разведения и коллекционирования кошек с блокчейном. Эта сенсационная игра — лишь один творческий пример практически неограниченного количества возможностей.

Хотя это кажется очень сложным, определенные фреймворки и инструменты были разработаны, чтобы отвлечь ваше взаимодействие с блокчейном и смарт-контрактами. В этой публикации блога я расскажу об одном из способов создания программы для децентрализованного голосования на Ethereum. Я кратко расскажу о Ethereum, но вам, вероятно, следует знать его, чтобы использовать это руководство как можно полнее. Кроме того, я ожидаю, что вы знаете Javascript.

Зачем создавать приложение для децентрализованного голосования?

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

По сути, блокчейн – это общий, программируемый, криптографически безопасный и, следовательно, надежный реестр, не контролирующий ни один пользователь и который может проверять кто-либо. – Клаус Шваб

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

Поскольку блокчейн — это постоянная запись распределяемых транзакций (голосов), каждый голос можно бесспорно отследить, когда и где он состоялся, не раскрывая личности избирателя. Кроме того, прошлые голоса не могут быть изменены, в то время как текущие не могут быть сломаны, поскольку каждая транзакция проверяется каждым отдельным узлом в сети. И любой внешний или внутренний злоумышленник должен иметь контроль над 51% узлов, чтобы изменить запись.

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

Основные компоненты Ethereum

Я ожидаю, что вы будете иметь понимание блокчейна и Ethereum к концу этого руководства. Вот замечательное руководство об этом, и я написал краткий обзор основных компонентов, которые я хотел бы вам знать.

  1. Умные контракты выполнять роль внутренней логики и хранилища. Контракт написан на Solidity, языке разумных контрактов и представляет собой набор кода и данных, находящихся по определенному адресу в блокчейне Ethereum. Это очень похоже на класс в объектно-ориентированном программировании, где он включает функции и переменные состояния. Смарт-контракты вместе с блокчейном являются основой всех децентрализованных программ. Они, как и Blockchain, неизменны и распространены, что означает, что обновить их будет трудно, если они уже есть в сети Ethereum. К счастью, вот несколько способов сделать это.
  2. Виртуальная машина Ethereum (EVM) обрабатывает внутреннее состояние и вычисление всей сети Ethereum. Подумайте об EVM как о массивном децентрализованном компьютере, содержащем «адреса», которые способны выполнять код, изменять данные и взаимодействовать друг с другом.
  3. Web3.js это Javascript API, который позволяет взаимодействовать с Blockchain, включая осуществление транзакций и вызовов смарт-контрактов. Этот API абстрагирует связь с клиентами Ethereum, позволяя разработчикам сосредоточиться на содержимом своей программы. Для этого в вашем браузере должен быть встроен экземпляр web3.

Другие инструменты, которые мы будем использовать

  1. трюфель это популярная платформа разработки тестирования для Ethereum. Он включает в себя блокчейн разработки, сценарии компиляции и миграции для развертывания вашего контракта в блокчейне, тестирование контракта и т.д. Это упрощает развитие!
  2. Трюфельные контракты — это абстракция на основе Web3 Javascript API, позволяющая легко подключаться и взаимодействовать с вашим смарт-контрактом.
  3. Метамаска переносит Ethereum в ваш браузер. Это расширение для браузера, которое предоставляет безопасный экземпляр web3, связанный с вашим адресом Ethereum, позволяющим использовать децентрализованные приложения. Мы не будем использовать Metamask в этом руководстве, но это способ для людей взаимодействовать с вашим DApp в производстве. При разработке мы введем собственный экземпляр web3. Дополнительные сведения см. в этой ссылке.

Давайте начнем!

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

Таким образом, мы сможем сосредоточить процесс создания смарт-контрактов и взаимодействия с ними в программе. Исходный код для всей программы будет в этом репозитории и вам нужно будет установить Node.js и npm.

Сначала давайте установим Truffle глобально.

npm install -g truffle

Чтобы использовать команды Truffle, их нужно запустить в существующем проекте.

git clone  truffle-webpack-boilerplatenpm install

Этот репозиторий является лишь скелетом Truffle Box, являющимся шаблонами или примерами программ, которые можно получить одной командой. truffle unbox [box name]. Однако коробка Truffle с веб-пакетом не обновляется последними версиями и содержит пример программы. Таким образом, я создал это репо (ссылка на которую приведена в инструкциях выше).

2. Структура каталога

Ваша структура каталога должна содержать:

  • contracts/ – Папка со всеми контрактами. НЕ УДАЛЯТЬ Migrations.sol
  • migrations/ — Папка с файлами миграции, помогающими разворачивать ваши смарт-контракты в Blockchain.
  • src/ — содержит файлы HTML/CSS и Javascript для программы
  • truffle.js — Файл конфигурации Truffle
  • build/ — Вы не увидите эту папку, пока не заключите свои договоры. Эта папка содержит артефакты сборки, поэтому не изменяйте ни один из этих файлов! Артефакты сборника описывают функцию и архитектуру вашего контракта и предоставляют контрактам Truffle и web3 информацию о том, как взаимодействовать с вашим разумным контрактом в блокчейне.

1. Напишите свои разумные контракты

Достаточно с настройкой и введением. Давайте разберемся с кодом! Во-первых, мы напишем наш смарт-контракт, который написан на Solidity (другие языки не так популярны). Это может показаться пугающим, но это не так.

Для любого применения, вы хотите, чтобы ваши разумные контракты были максимально простыми, даже очень простыми. Помните, что вы должны платить за каждое вычисление/транзакцию, которую вы производите, и ваши разумные контракты будут у Blockchain навсегда. Итак, вы действительно хотите, чтобы он работал идеально, то есть чем сложнее он, тем легче совершить ошибку.

Наш контракт будет включать:

  1. Переменные состояния — переменные, содержащие постоянно хранящиеся в Blockchain значения. Мы будем использовать переменные состояния для хранения списка и количества избирателей и кандидатов.
  2. Функции – Функции – это исполняемые файлы смарт-контрактов. Это то, что мы будем вызывать для взаимодействия с Blockchain, и они имеют разные уровни видимости, внутренней и внешней. Имейте в виду, что если вы хотите изменить значение/состояние переменной, должна произойти транзакция – стоимость Ether. Вы также можете сделать calls к Blockchain, который не будет стоить ни одного эфира, поскольку внесенные вами изменения будут уничтожены (больше об этом в Главе 3, когда мы фактически сделаем transactions и calls).
  3. События — Каждый раз, когда вызывается событие, значение, переданное в событие, будет зарегистрировано в журнале транзакций. Это позволяет функциям обратного вызова Javascript или разрешенным обещаниям просматривать определенное значение, которое вы хотите передать после транзакции. Это объясняется тем, что каждый раз, когда вы совершаете транзакцию, возвращается журнал транзакций. Мы будем использовать событие для регистрации идентификатора недавно созданного Кандидата, который мы отразим (проверьте первый пункт раздела 3).
  4. Типы структур — Это очень похоже на структуру C. Структуры позволяют хранить несколько переменных и отлично подходят для вещей с несколькими атрибутами. Candidates будет иметь только название и партию, но вы точно можете добавить больше атрибутов.
  5. Отображение — Представьте это как хэш-карты или словари, где есть пара ключ-значения. Мы будем использовать два отображения.

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

Для справки, вот код смарт-контракта. Обратите внимание, что этот файл должен быть вызван. Voting.sol но я хотел, чтобы суть Github имела стиль, поэтому я сделал это .js расширение. Как и в остальном пособия, я даю комментарии в коде, которые будут объяснять, что он делает, а затем я объясню общую картину, указывая на определенные оговорки и логику.

По сути у нас есть две структуры (типы, содержащие несколько переменных), которые описывают Избирателя и Кандидата. С помощью Structs мы можем назначить несколько свойств, например электронные адреса, адрес и т.д.

Чтобы отслеживать избирателей и кандидатов, мы помещаем их в отдельные отражения, где они имеют целочисленный индекс. Индекс/ключ кандидата или избирателя – назовем это идентификатором – это единственный способ для функций доступа к ним.

Мы также отслеживаем количество избирателей и кандидатов, что поможет нам индексировать их. Кроме того, не забудьте о событии в строке 8, которое будет регистрировать идентификатор кандидата, когда он добавлен. Это событие будет использовать наш интерфейс, поскольку нам нужно отслеживать идентификатор кандидата, чтобы проголосовать за него.

  1. Я знаю, что вопреки тому, что я говорил раньше о том, что сделать контракты чрезвычайно простыми, я сделал этот контракт несколько сложнее по сравнению с тем, что на самом деле делает эта программа. Однако я сделал это для того, чтобы вам, ребята, было гораздо легче редактировать и добавлять функции в эту программу позже (подробнее об этом в конце). Если вы хотите создать еще более простое приложение для голосования, смарт-контракт может работать в менее чем 15 строках кода.
  2. Обратите внимание, что переменные состояния numCandidates и numVoters не объявляются публичными. По умолчанию эти переменные имеют видимость internalчто означает, что к ним можно получить прямой доступ только посредством текущего контракта или производных контрактов (не волнуйтесь, мы не будем этим пользоваться).
  3. Мы используем 32bytes для строк вместо использования string типа. Наш EVM имеет размер слова 32 байта, поэтому он оптимизирован для работы с данными во фрагментах по 32 байта. (Компиляторам, таким как Solidity, приходится выполнять больше работы и генерировать больше байт-кода, когда данные не содержат фрагментов по 32 байта, что фактически приводит к более высоким затратам на газ.)
  4. Когда пользователь голосует, новый Voter struct создается и добавляется к отображению. Чтобы подсчитать количество голосов кандидата, вы должны прокрутить всех избирателей и подсчитать количество голосов. Кандидаты действуют так же. Таким образом, эти отражения будут содержать историю всех кандидатов и избирателей.

2. Создание экземпляров web3 и контрактов

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

Прежде чем запустить наш тестовый блокчейн, мы должны создать файл под названием 2_deploy_contracts.js внутри папки /contracts которая указывает включить ваш смарт-контракт голосования при переходе.

Чтобы начать разработку блокчейна Ethereum, выделите командную строку и выполните:

truffle develop

Это будет жить в вашей командной строке. Поскольку Solidity является скомпилированным языком, мы должны сначала скомпилировать его в байт-код для выполнения EVM.

compile

Вы должны увидеть a build/ сейчас в вашем каталоге. В этой папке хранятся артефакты сборника, которые имеют решающее значение для внутренней работы Truffle, поэтому не трогайте их!

Дальше мы должны перенести договор. Migrations – это сценарий Truffle, который помогает изменять состояние контракта вашей программы при разработке. Помните, что ваш контракт развертывается по определенному адресу в Blockchain, поэтому каждый раз, когда вы вносите изменения, ваш контракт будет размещен по другому адресу. Миграции помогают вам сделать это, а также помогают перемещать данные.

migrate

Поздравляю! Ваш смарт-контракт теперь у Blockchain навсегда. Ну не совсем… поскольку truffle develop обновляется каждый раз, когда вы его останавливаете.

Если вы хотите иметь постоянный блокчейн, рассмотрит Ganache, который также разработан Truffle. Если вы используете Ganache, вам не нужно будет звонить truffle develop. Вместо этого вы будете бегать truffle compile и truffle migrate. Чтобы понять, что действительно нужно для развертывания контракта без Truffle, просмотрите эту публикацию в блоге.

После того, как мы развернули смарт-контракт в Blockchain, нам придется настроить экземпляр web3.0 с Javascript в браузере при каждом запуске программы. Следовательно, следующий фрагмент кода будет размещен внизу js/app.js. Обратите внимание, что мы используем web3.0 версии 0.20.1.

Вам не нужно слишком переживать, если вы не понимаете этот код. Просто знайте, что это будет запущено при запуске программы и проверит, есть ли экземпляр web3 (Metamask) в вашем браузере. Если его нет, мы просто создадим такой, который будет общаться с localhost:9545который является блокчейном разработкой Truffle.

Если вы используете Ganache, вам нужно изменить порт на 7545. После создания экземпляра мы вызовем start функция (я определю ее в следующей главе).

3. Добавьте функциональность

Остальное, что нам нужно сделать, это написать интерфейс программы. Это включает в себя основные элементы для любой веб-приложения – HTML, CSS и Javascript (мы уже написали немного о Javascript с созданием экземпляра web3). Сначала давайте создадим наш HTML файл.

Это очень простая страница с формой ввода идентификатора пользователя и кнопками для голосования и подсчета голосов. Когда эти кнопки нажимаются, они вызывают определенные голосующие функции и определяют количество голосов за кандидатов.

Есть три важных элемента div с идентификаторами: candidate-box, msgи vote-box, в котором будут размещены флажки для каждого кандидата, сообщения и количество голосов соответственно. Мы также импортируем JQuery, Bootstrap и app.js.

Теперь нам остается только взаимодействовать с Договором и реализовать функции голосования и подсчета голосов каждого кандидата. JQuery будет манипулировать DOM, и мы будем использовать Promises при совершении транзакций или вызовов в Blockchain. Ниже приведен код для app.js.

Обратите внимание, что код, который я предоставил в предыдущем шаге для создания экземпляра web3, также здесь. Во-первых, мы импортируем необходимые библиотеки и материалы для веб-пакетов, включая контракты Web3 и Truffle. Мы будем использовать Truffle Contracts, которые построены на основе web3 для взаимодействия с Blockchain.

Чтобы использовать его, мы возьмем артефакты сборника, автоматически созданные во время компиляции разумного контракта для голосования, и используем их для создания контракта Truffle. Наконец, мы устанавливаем функции в глобальной переменной window для запуска программы, голосования за кандидата и определения количества голосов.

Чтобы реально взаимодействовать с Blockchain, мы должны создать экземпляр контракта Truffle с помощью deployed функция. Это, в свою очередь, вернет обещание с экземпляром как значение, которое вы будете использовать для вызова функций смарт-контракта.

Есть два способа взаимодействия с этими функциями: транзакции и вызовы. Транзакция является операцией записи, и она будет транслироваться по всей сети и обрабатываться майнерами (и, следовательно, стоит Ether). Вы должны выполнить транзакцию, если вы изменяете переменное состояние, поскольку это изменит состояние блокчейна.

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

Чтобы заключить транзакцию с Truffle Contracts, вы пишете instance.functionName(param1, param2)с instance как экземпляр, который был возвращен deployed функция (Проверьте строку 36 для примера). Эта транзакция вернет обещание с данными транзакции как возвращенным значением. Таким образом, если вы возвращаете значение в своей функции смарт-контракта, но выполняете транзакцию с помощью той же функции, она не вернет это значение.

Вот почему у нас есть событие, которое будет регистрировать все, что вы хотите, чтобы оно записывало в данные транзакции, которые будут возвращены. В случае строк 36–37 мы выполняем транзакцию для добавления кандидата. Когда мы решаем обещание, мы получаем данные транзакции result.

Чтобы получить candidateID которые мы зарегистрировали вместе с событием AddedCandidate() (проверьте смарт-контракт, чтобы увидеть его 0), мы должны просмотреть журналы и получить его так: result.logs[0].args.candidateID.

Чтобы увидеть, что происходит, используйте инструменты разработчика Chrome, чтобы распечатать result и рассмотрите его структуру result.

Чтобы позвонить, напишите instance.functionName.call(param1,param2). Однако, если функция имеет ключевое слово viewтогда Truffle Contracts автоматически создаст вызов, поэтому вам не нужно добавлять .call.

Вот почему наши функции получения имеют view ключевое слово. В отличие от транзакции, возвращенное обещание вызова будет иметь значение, возвращаемое функцией смарт-контракта.

Сейчас я кратко объясню 3 функции, но это должно быть очень знакомо, если вы создали программы, которые получают/изменяют данные из хранилища данных и соответственно манипулируют DOM. Подумайте о Blockchain как о своей базе данных, а о Truffle Contracts как об API для получения данных из вашей базы данных.

App.start()

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

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

Когда все настроено, мы отразим флажки для каждого кандидата, чтобы пользователь мог проголосовать. Для этого мы должны создать экземпляр договора и получить информацию о кандидате. Если кандидатов не будет, мы их создадим. Чтобы пользователь мог проголосовать за кандидата, мы должны предоставить идентификатору этого кандидата. Таким образом, каждый элемент флажка имеет id(атрибут элемента HTML) идентификатора кандидата Кроме того, мы добавим количество кандидатов в глобальную переменную. numOfCandidatesкоторый мы будем использовать в App.findNumOfVotes(). JQuery используется для добавления каждого флажка и его имени кандидата .candidate-box.

App.vote()

Эта функция будет голосовать за определенного кандидата в зависимости от того, какой флажок установлен и его id атрибут.

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

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

После завершения транзакции мы решим возвращенное обещание и отразим сообщение «Проголосовано».

App.findNumOfVotes()

Эта последняя функция найдет количество голосов каждого кандидата и отобразит их. Мы просмотрим кандидатов и вызовем две функции смарт-контракта, getCandidate и totalVotes. Мы решим эти обещания и создадим элемент HTML для конкретного кандидата.

Теперь запустите программу, и вы увидите ее http://localhost:8080/!

npm run dev

Ресурсы

Я знаю, это много… Возможно, эта статья будет открыта некоторое время, пока вы медленно разрабатываете это приложение и действительно понимаете, что происходит. Но это обучение! Пожалуйста, дополните это руководство всей документацией из Ethereum, Truffle и тем, что я предоставил ниже. Я пытался осветить многие ключевые моменты в этой статье, но это лишь краткий обзор, и эти ресурсы очень помогут.

Вывод

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

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

  • Отразите партию каждого кандидата. Мы уже получаем партию кандидата, когда баллотируемся getCandidate(id).
  • Убедитесь, что идентификатор, введенный пользователем, уникален.
  • Запрашивать и сохранять больше информации о Пользователе, например, дата рождения и домашний адрес.
  • Добавьте опцию, чтобы увидеть, голосовало лицо с определенным идентификатором или нет. Вы должны создать новую форму для ввода идентификатора, по которому затем будете искать определенного пользователя в блокчейне.
  • Напишите новую функцию смарт-контракта, которая подсчитывает голоса за обоих кандидатов одновременно. Теперь мы должны совершить два отдельных звонка для двух кандидатов, требуя, чтобы контракт дважды прошел через всех пользователей.
  • Разрешить добавлять новых кандидатов. Это означает добавить новую форму для добавления кандидатов, а также изменить способ отображения и голосования за кандидатов в интерфейсе.
  • Требуйте от пользователей иметь адрес Ethereum для голосования. Моя логика не включать адреса пользователей в том, что избиратели не ожидают, что Ethereum участвует в этом процессе голосования. Однако многие DApps потребуют от пользователей иметь адрес Ethereum.

Кроме того, вот несколько советов, которые могут предотвратить возникновение некоторых блокпостов:

  • Дважды и тройно проверяйте функции смарт-контракта, когда происходит что-то странное. Я потратил несколько часов на ошибку, чтобы понять, что я вернул неправильное значение в одной из своих функций.
  • Проверьте правильность URL-адреса и порта при подключении к блокчейной разработке. Помните: 7545 для truffle develop и 9545 для ганаша. Это по умолчанию, поэтому если вы не можете подключиться к своему блокчейну, возможно, вы их изменили.
  • Я не рассматривал это, потому что это руководство было бы слишком длинным, и я, вероятно, напишу об этом еще одну публикацию – но вы должны проверить свои контракты! Это очень поможет.
  • Если вы не знакомы с промесями, ознакомьтесь с тем, как они работают и как ими пользоваться. Truffle Contracts использует обещания, а бета-версия для web3 будет поддерживать обещания. Если вы сделаете их неправильно, они могут испортить множество данных, которые вы получаете.

Поздравляем с работой над децентрализованным и безопасным Интернетом – Web 3.0!

Надеюсь, вам понравилось читать это руководство так же, как мне было приятно его писать! Если у вас есть какие-либо мнения или комментарии, не стесняйтесь оставить комментарий ниже или написать мне по электронной почте на tk2@illinois.edu или написать мне в Twitter (я недавно создал один)! Не стесняйтесь использовать мой код и поделиться им с друзьями!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *