Ръководство за разработване на децентрализирано приложение за гласуване на Ethereum

След като целият пазар на криптовалути достигна 700 милиарда долара пазарна капитализация, пространството на криптовалутите експлодира през последните няколко месеца. Но това е само началото. Тъй като блокчейн системите продължават да се развиват и мащабират, един чудесен начин да се потопите в това ново пространство и да използвате тази технология е с децентрализирани приложения, известни иначе като dApps.

CryptoKitties, известен с претоварването на Ethereum Blockchain, е чудесен пример за dApp, уникално съчетаващ концепциите за размножаващи се и колекционерски котки с blockchain. Тази сензационна игра е само един творчески пример от практически неограничен брой възможности.

Макар да изглеждат много сложни, са разработени определени рамки и инструменти за абстрахиране на вашите взаимодействия с блокчейн и интелигентните договори. В тази публикация в блога ще разгледам един от начините да създам децентрализирано приложение за гласуване в Ethereum. Ще разгледам накратко Ethereum, но вероятно трябва да го разберете, за да използвате това ръководство в пълна степен. Освен това очаквам да знаете Javascript.

Защо да направим приложение за децентрализирано гласуване?

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

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

Въпреки че приложението за гласуване може да не е чудесно приложение за потребителите, избрах да го използвам за това ръководство, защото основните проблеми, които блокчейнът решава - прозрачност, сигурност, достъпност, чуваемост - са основните проблеми, които тормозят настоящите демократични избори.

Тъй като блокчейнът е постоянен запис на транзакции (гласове), които се разпределят, всеки глас може да бъде неопровержимо проследен точно до кога и къде се е случил, без да се разкрива самоличността на избирателя. Освен това миналите гласове не могат да бъдат променени, докато настоящите не могат да бъдат хакнати, тъй като всяка транзакция се проверява от всеки отделен възел в мрежата. И всеки нападател отвън или отвътре трябва да има контрол над 51% от възлите, за да промени записа.

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

Основни компоненти на Ethereum

Очаквам да имате разбиране за Blockchain и Ethereum до края на това ръководство. Ето страхотно ръководство за това и аз написах кратък преглед на основните компоненти, които бих искал да знаете.

  1. Интелигентните договори действат като логика и съхранение. Договорът е написан на Solidity, интелигентен език на договора, и представлява колекция от код и данни, които се намират на определен адрес в блокчейна Ethereum. Той е много подобен на клас в обектно-ориентирано програмиране, където включва функции и променливи на състоянието. Интелигентните договори, заедно с Blockchain, са в основата на всички децентрализирани приложения. Те са, подобно на Blockchain, неизменни и разпределени, което означава, че надграждането им ще бъде болка, ако вече са в мрежата Ethereum. За щастие, ето няколко начина да направите това.
  2. Виртуалната машина Ethereum (EVM) обработва вътрешното състояние и изчисляването на цялата мрежа Ethereum. Мислете за EVM като за този масивен децентрализиран компютър, който съдържа „адреси“, които могат да изпълняват код, да променят данни и да си взаимодействат помежду си.
  3. Web3.jsе Javascript API, който ви позволява да взаимодействате с Blockchain, включително извършване на транзакции и обаждания към интелигентни договори. Този API абстрахира комуникацията с клиенти на Ethereum, позволявайки на разработчиците да се съсредоточат върху съдържанието на тяхното приложение. Трябва да имате вграден екземпляр web3 в браузъра си, за да го направите.

Други инструменти, които ще използваме

  1. Трюфеле популярна рамка за разработване на тестове за Ethereum. Той включва скриптове за разработка на блокове, компилация и миграция за разполагане на вашия договор в блокчейн, тестване на договори и т.н. Улеснява развитието!
  2. Договорите за трюфели е абстракция върху Web3 Javascript API, която ви позволява лесно да се свързвате и да взаимодействате с вашия интелигентен договор.
  3. Metamask въвежда Ethereum във вашия браузър. Това е разширение на браузъра, което осигурява защитен екземпляр на web3, свързан с вашия адрес в Ethereum, което ви позволява да използвате децентрализирани приложения. В този урок няма да използваме Metamask, но това е начин хората да взаимодействат с вашия DApp в производството. Вместо това ще инжектираме собствения си web3 екземпляр по време на разработката. За повече информация вижте тази връзка.

Да започваме!

За простота всъщност няма да изграждаме пълната система за гласуване, която описах по-рано. За по-лесно обяснение, това ще бъде само приложение от една страница, където потребителят може да въведе своя документ за самоличност и да гласува за кандидат. Ще има и бутон, който отчита и показва броя на гласовете на кандидат.

По този начин ще можем да фокусираме процеса на създаване и взаимодействие със смарт договорите в рамките на приложение. Изходният код за цялото това приложение ще бъде в това хранилище и ще трябва да имате инсталирани Node.js и npm.

Първо, нека да инсталираме Truffle глобално.

npm install -g truffle

За да използвате команди за трюфели, трябва да ги стартирате в съществуващ проект.

git clone //github.com/tko22/truffle-webpack-boilerplatecd truffle-webpack-boilerplatenpm install

Това хранилище е само скелет на трюфелна кутия, които са бойлери или примерни приложения, които можете да получите с една команда - truffle unbox [box name]. Кутията за трюфели с уеб пакет обаче не се актуализира с най-новите версии и включва примерно приложение. По този начин създадох това репо (свързаното в инструкциите по-горе).

2. Структура на директорията

Структурата на вашата директория трябва да включва следните:

  • contracts/- Папка, съдържаща всички договори. НЕ ИЗТРИВАЙТЕMigrations.sol
  • migrations/ - Папка, съдържаща файлове за миграция, които ви помагат да внедрите вашите интелигентни договори в Blockchain.
  • src/ - съхранява HTML / CSS и Javascript файловете за приложението
  • truffle.js - Конфигурационен файл за трюфел
  • build/- Няма да видите тази папка, докато не съставите договорите си. Тази папка съдържа артефакти за изграждане, така че не променяйте нито един от тези файлове! Артефактите за изграждане описват функцията и архитектурата на вашия договор и дават договори за трюфели и web3 информация за това как да взаимодействате с вашия интелигентен договор в Blockchain.

1. Напишете вашите интелигентни договори

Стига с настройката и въвеждането. Нека да влезем в кода! Първо ще напишем нашия интелигентен договор, който е написан на Solidity (другите езици не са толкова популярни). Може да изглежда страшно, но не е така.

За всяко приложение искате вашите интелигентни договори да бъдат възможно най-опростени, дори глупаво прости. Не забравяйте, че трябва да плащате за всяко изчисление / транзакция, която правите, и вашите интелигентни договори ще останат завинаги на Blockchain . Така че, вие наистина искате тя да работи перфектно - което означава, че колкото по-сложна е тя, толкова по-лесно е да сгрешите.

Нашият договор ще включва:

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

Има още няколко типа, които не са изброени тук, но някои от тях са малко по-сложни. Тези пет обхващат много от структурите, които един интелигентен договор обикновено ще използва. Тези видове са обяснени по-задълбочено тук.

За справка ето кода на интелигентния договор. Имайте предвид, че този файл трябва да се извика, Voting.solно исках Gistub да има стилистика, затова му дадох .jsразширение. Подобно на останалата част от това ръководство, ще дам коментари в кода, които ще обяснят какво прави и ще обясня общата картина след това, като посоча някои предупреждения и логика.

По принцип имаме две структури (типове, които съдържат множество променливи), които описват избирател и кандидат. С помощта на структури можем да им присвояваме множество свойства, като имейли, адрес и т.н.

За да следим избирателите и кандидатите, ги поставяме в отделни картографирания, където те са индексирани с цяло число. Индексът / ключът на кандидат или избирател - позволява да го наречем ID - е единственият начин за достъп до функциите .

Ние също така следим броя на избирателите и кандидатите, което ще ни помогне да ги индексираме. Освен това не забравяйте за събитието в ред 8, което ще регистрира идентификационния номер на кандидата, когато бъде добавен. Това събитие ще се използва от нашия интерфейс, тъй като трябва да следим идентификационния номер на кандидата, за да гласуваме за него.

  1. Знам, че противно на казаното по-рано за правенето на свръхпрости договори, направих този договор малко по-сложен в сравнение с това, което всъщност прави това приложение. Направих това обаче, за да бъде много по-лесно за вас да правите редакции и да добавяте функции към това приложение след това (повече за това в края). Ако искате да направите още по-просто приложение за гласуване, интелигентният договор може да работи в по-малко от 15 реда код.
  2. Имайте предвид, че променливите на състоянието numCandidatesи numVotersне са обявени за обществени. По подразбиране тези променливи имат видимост на internal, което означава, че те могат да бъдат директно достъпни само от текущия договор или производни договори (не се притеснявайте за това, няма да го използваме).
  3. Използваме 32bytesза низове, вместо да използваме stringтипа. Нашият EVM има размер на думата от 32 байта, така че е „оптимизиран“ за работа с данни на парчета от 32 байта. (Компилаторите, като Solidity, трябва да свършат повече работа и да генерират повече байт код, когато данните не са на парчета от 32 байта, което ефективно води до по-високи разходи за газ.)
  4. Когато потребителят гласува, се създава нова Voterструктура и се добавя към картографирането. За да преброите броя на гласовете, които има определен кандидат, трябва да прегледате всички избиратели и да преброите броя на гласовете. Кандидатите оперират със същото поведение. По този начин тези карти ще съдържат историята на всички кандидати и избиратели.

2. Инстанцирайте web3 и договори

След като завършим нашия интелигентен договор, сега трябва да стартираме нашата тестова блокчейн и да разположим този договор върху блокчейна. Ще ни е необходим и начин за разговор с него, който ще бъде чрез web3.js.

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

За да стартирате блокчейна за развитие Ethereum, отидете в командния ред и стартирайте:

truffle develop

Това ще се появи на вашия команден ред. Тъй като Solidity е компилиран език, първо трябва да го компилираме в байт код, за да се изпълни EVM.

compile

Трябва да видите build/папка във вашата директория сега. Тази папка съдържа артефакти за изграждане, които са от решаващо значение за вътрешната работа на Трюфел, така че не ги докосвайте!

След това трябва да мигрираме договора. Migrations е скрипт за трюфел, който ви помага да промените състоянието на договора на вашето приложение, докато се развивате. Не забравяйте, че договорът ви е разположен на определен адрес в Blockchain, така че всеки път, когато правите промени, договорът ви ще се намира на различен адрес. Миграциите ви помагат да направите това, а също и да премествате данни.

migrate

Честито! Вашият интелигентен договор вече е на Blockchain завинаги. Е, всъщност не ... защото се truffle developосвежава всеки път, когато го спрете.

Ако искате да имате постоянна блокчейн, помислете за Ganache, който също е разработен от Truffle. Ако използвате Ganache, няма да е необходимо да се обаждате truffle develop. Вместо това ще тичате truffle compileи truffle migrate. За да разберете какво всъщност е необходимо за разполагане на договор без трюфел, разгледайте тази публикация в блога.

След като разгърнем интелигентния договор в Blockchain, ще трябва да настроим екземпляр web3.0 с Javascript в браузъра, когато приложението стартира. По този начин следващата част от кода ще бъде поставена в долната част на js/app.js. Имайте предвид, че използваме web3.0 версия 0.20.1.

Всъщност не трябва да се притеснявате твърде много, ако не разбирате този код. Просто знайте, че това ще се стартира при стартиране на приложението и ще провери дали в браузъра ви вече има екземпляр web3 (Metamask). Ако няма, ние просто ще създадем такъв, който да разговаря localhost:9545, който е блокчейнът за развитие на трюфели.

Ако използвате 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, също е тук. Първо, ние импортираме необходимите библиотеки и неща от webpack, включително web3 и договори за трюфели. Ще използваме договори за трюфели, който е изграден върху web3 за взаимодействие с Blockchain.

За да го използваме, ще вземем артефактите за компилация, които са били автоматично създадени, когато сме съставили интелигентния договор за гласуване, и ще ги използваме за създаване на договор за трюфел. Накрая зададохме функциите в глобалната променлива windowза стартиране на приложението, гласуване за кандидат и намиране на броя гласове.

За да взаимодействаме действително с Blockchain, трябва да създадем екземпляр на Договора за трюфел, като използваме deployedфункцията. Това от своя страна ще върне обещание с екземпляра като върната стойност, която ще използвате за извикване на функции от интелигентния договор.

Има два начина за взаимодействие с тези функции: транзакции и обаждания. Транзакцията е операция за запис и тя ще бъде излъчена до цялата мрежа и ще бъде обработена от майнери (и по този начин струва Ether). Трябва да извършите транзакция, ако променяте променлива на състоянието, тъй като тя ще промени състоянието на блокчейна.

Обаждането е операция за четене, симулираща транзакция, но отхвърляща промяната в състоянието. По този начин няма да струва Ether. Това е чудесно за извикване на getter функции (вижте четирите getter функции, които написахме преди в нашия интелигентен договор).

За да направите транзакция с договори за трюфели, вие пишете 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, тогава трюфелните договори автоматично ще създадат повикване и по този начин не е необходимо да добавяте .call.

Ето защо нашите функции за получаване имат viewключовата дума. За разлика от извършването на транзакция, върнатото обещание за разговор ще има върната стойност на каквото и да е върнато от функцията за интелигентен договор.

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

App.start ()

Тази функция се извиква веднага след като създадем екземпляр web3. За да заработят договори за трюфели, трябва да настроим доставчика на създадения екземпляр web3 и да зададем настройки по подразбиране (като кой акаунт използвате и количеството газ, което искате да платите, за да извършите транзакция).

Тъй като сме в режим на разработка, можем да използваме всяко количество газ и всяка сметка. По време на производството бихме взели сметката, предоставена от MetaMask, и ще се опитаме да разберем най-малкото количество газ, което бихте могли да използвате, тъй като всъщност това са реални пари.

С всичко настроено, сега ще покажем квадратчетата за отметка за всеки кандидат, за който потребителят да гласува. За целта трябва да създадем екземпляр на договора и да получим информацията за кандидата. Ако няма кандидати, ние ще ги създадем. За да може потребителят да гласува за кандидат, трябва да предоставим идентификационния номер на този определен кандидат. По този начин правим всеки елемент в квадратчето да има id(атрибут HTML елемент) на идентификатора на кандидата. Освен това ще добавим броя на кандидатите към глобална променлива numOfCandidates, която ще използваме в App.findNumOfVotes(). JQuery се използва за добавяне на всяко квадратче за отметка и името на неговия кандидат .candidate-box.

App.vote ()

Тази функция ще гласува за определен кандидат въз основа на коя отметка е щракната и нейния idатрибут.

Първо, ще проверим дали потребителят е въвел своя userID, който е неговата идентификация. Ако не го направят, показваме съобщение, което им казва да го направят.

Второ, ще проверим дали потребителят гласува за кандидат, като проверим дали има поне едно квадратче за отметка. Ако нито едно от квадратчетата за отметка не е щракнато, ние също ще покажем съобщение, което им казва да гласуват за кандидат. Ако едно от квадратчетата за отметка бъде щракнато, ще вземем idатрибута на това квадратче, който е и идентификационният номер на свързания кандидат, и ще използваме това, за да гласуваме за кандидата.

След като транзакцията приключи, ние ще разрешим върнатото обещание и ще покажем съобщение „Гласувано“.

App.findNumOfVotes ()

Тази последна функция ще намери броя гласове за всеки кандидат и ще ги покаже. Ще преминем през кандидатите и ще извикаме две функции за интелигентен договор getCandidateи totalVotes. Ще разрешим тези обещания и ще създадем HTML елемент за този определен кандидат.

Сега стартирайте приложението и ще го видите //localhost:8080/!

npm run dev

Ресурси

Знам, че е много ... Може тази статия да бъде отворена за известно време, докато бавно разработвате това приложение и наистина разбирате какво се случва. Но това е ученето! Моля, допълнете това ръководство с цялата документация от Ethereum, Truffle и това, което предоставих по-долу. Опитах се да засегна много от ключовите моменти в тази статия, но това е само кратък преглед и тези ресурси ще помогнат много.

  • Всичко за солидността и интелигентните договори - имам предвид всичко
  • Всичко за трюфела
  • Документи за договори за трюфели
  • API на Web3 Javascript- това ще бъде чудесно да се знае и да се направи справка, но договорите за трюфели абстрахират много части от това
  • Полезни DApp модели
  • Ethereum Docs - погледнете страничната лента и има много неща
  • Обяснение на кода на CryptoKitties - Сценаристът преминава през важните части на Smart Contract на CryptoKitties
  • Най-добри практики за интелигентен договор- задължително четене

Заключение

Изграждането на приложения на Ethereum е доста подобно на обикновеното приложение, извикващо бекенд услуга. Най-трудното е да напишеш стабилен и пълен интелигентен договор. Надявам се това ръководство да ви е помогнало да разберете основните познания на децентрализираните приложения и Ethereum и ще ви помогне да започнете интереса си към тяхното разработване.

Ако искате да надградите изграденото от нас, ето няколко идеи. Всъщност написах интелигентния договор по такъв начин, че да се изпълнява лесно с всичко, което ви дадох в това ръководство.

  • Покажете партията на всеки кандидат. Вече получаваме партията на кандидат, когато се кандидатираме getCandidate(id).
  • Проверете дали въведеният от потребителя ID е уникален.
  • Попитайте и съхранявайте повече информация за Потребител, като например рождената му дата и домашния адрес.
  • Добавете опция, за да видите дали човек с определен идентификатор е гласувал или не. Бихте създали нов формуляр за въвеждане в идентификатор, който след това бихте потърсили за този определен потребител в блокчейна.
  • Напишете нова функция за интелигентен договор, която брои гласовете за И двамата кандидати наведнъж. Понастоящем трябва да направим две отделни повиквания за двама кандидати, изисквайки договорът да премине два пъти през всички Потребители.
  • Разрешаване на добавянето на нови кандидати. Това означава да добавите нов формуляр за добавяне на кандидати, но също така да промените малко начина, по който показваме и гласуваме за кандидати в интерфейса.
  • Изисквайте от потребителите да имат Ethereum адрес, за да гласуват. Моята логика да не включвам потребителски адреси е, защото от избирателите не се очаква да имат Ethereum за участие в този процес на гласуване. Много DApps обаче ще изискват от потребителите да имат адрес на Ethereum.

Също така, ето няколко съвета, които могат да предотвратят появата на някои пътни блокади:

  • Двойна и тройна проверка на функциите на вашия интелигентен договор, когато се случва нещо странно. Прекарах няколко часа в грешка, за да разбера, че съм върнал грешната стойност в една от функциите си.
  • Проверете дали вашият URL адрес и порт са правилни, когато се свързвате с вашата блокчейн за разработка. Запомнете: 7545е за truffle developи 9545е за Ганаш. Това са настройки по подразбиране, така че ако не можете да се свържете с вашата блокчейн, може би сте ги променили.
  • Не съм го обмислял, защото това ръководство би било твърде дълго и вероятно ще направя друга публикация за това - но трябва да тествате договорите си! Ще помогне много.
  • Ако не сте запознати с обещанията, разгледайте как работят и как да ги използвате. Truffle Contracts използва обещания, а бета версията за web3 също ще поддържа обещания. Те могат, ако ги сгрешите, да объркат голяма част от данните, които извличате.

Наздраве за работа към децентрализиран и сигурен интернет - Web 3.0!

Надявам се да ви е било приятно да прочетете това ръководство, както и аз да го пиша! Ако имате някакви мисли и коментари, не се колебайте да оставите коментар по-долу или да ми пишете на [email protected] или да ми пишете в чуруликане (наскоро го създадох)! Чувствайте се свободни да използвате моя код и да го споделите с приятелите си!