Giter VIP home page Giter VIP logo

voting-chain's Introduction

Voting Chain 🗳🗳🗳

Homepage

Table of Contents

Introducion

Voting Chain lets users in its system to nominate other users to various elections and vote for nominated users in various elections. An admin can create elections with various positions. Results are computed in such a way so that a user is announced winner to no more than one position. The main feature of this app is that all votes are stored on a blockchain structure and this blockchain is stored locally on every client and propagated peer-to-peer.

This project came out of a problem posed at Falguni Code Sprint 2019, a 36-hour hackathon hosted at ULAB, Dhaka, Bangladesh. I was not happy with the project I build there so I decided to redo it during my spare time. It was a great decision as I ended up learning lots of things and building this on my own was quite a lot of fun.

The following document outlines the tech stack, technical details of how the entire system works, implementation details for the blockchain and peer-to-peer (P2P) system, and "favorite" pieces of code that I wrote for this project.

Tech Stack

I picked Next.js because I was quite comfortable with React and using Next meant I got a really good routing api out of the box. Firebase was used for authentication and storing user data, elections list and nominations, however, all vote related information was stored on the blockchain.

Jest

This was my first time writing tests of any kind and so I picked Jest as everyone on the internet recommended it. I have very few tests in my codebase and they only test complicated units. I am planning on learning how to test UI since I found manually testing things to be really error prone and time consuming.

Tailwind.css

I have always used Harry Robert's ITCSS/BEM methodology when writing CSS. However, during this project, I found myself being slowed down having to think of semantic classnames and think of when to make an object and when to make a component. To address this frustration of not being able to move quickly and change things, I started looking into Atomic CSS. Later, after listening to Jeffrey Way on Fullstack Radio I decided to use Tailwind.css.

Overall, I like the utility-first css approach of tailwind, however without adhering to its "extracting components" principle and without properly configuring the tailwind.config.js file, I found my html quickly becoming a class soup. I found Harry Robert's advice on modular css to be helpful when taking this modular/atomic approach to authoring css.

Typescript

I had started the project with the opinion that types are too verbose and unnecessary. But, when I was trying to write the DataProvider Component, which was responsible for pulling in data from Firebase and exposing it to other components, I found Typescript's interface definitions and typechecking to be a God send. It not only threw type errors in real that saved me a lot of debugging time but also gave me confidence that I wouldn't mutate a data structure in an unexpected way. Furthermore, Next.js out of the box typescript support made incrementally adopting it a breeze.

Technical Details

The Blockchain

The steps of how a vote is added to the blockchain is as follows: The code corresponding to each step is also linked.

  1. A user votes for a nominee in an election for a certain position. code
  2. The vote is signed using the users private key. code
  3. The vote is propagated to all the peers in the network. code
  4. Each peer puts the vote in a mining queue. code
  5. A Web Worker watches the mining queue, and processes (finds a hash and nonce) each vote sequentially. code
  6. Once a vote has been mined by a peer, the peer sends that block to all the peers in the network. code
  7. When a peer receives a block, it makes sure the vote contained in that block is valid (as per the spec) and if it is, it adds it to its local blockchain. code
  8. Once the in-memory blockchain is updated, it is persisted on the client by using localstorage. code

The P2P Network

Each client connects to other clients using WebRTC. The connection is made by the simple-peer package and peer discovery is done using the webrtc-swarm package.

The network is exposed as a react hook. It returns a list of peers, a function to send votes to the network and a function to send blocks (mined votes) to the network. It takes two functions as arguments, which listens for new votes and new blocks from the network respectively.

Clients are connected to a signalhub server which brokers the webrtc connection between peers. No data flows through the server.

Calculating Results

In an election, winners are determined in a such a way so that no user wins in more than one position. The following rules also apply:

  • Highest voted user in category wins
  • If a user has a vote count of 5 in position A an a vote count of 8 for position B, then the user wins in position B.
  • if a user has vote count of 5 for both position A and B, then the result for that position is on hold and must be determined by the admin.
  • If two or more users in the same position has equal number of votes, then the election goes on hold

On the admin side, for elections on hold, the admin is allowed to make a special vote after the election has ended, to determine the winner.

Side note: Figuring out an algorithm to determine the results was a rewarding, albeit quite painful, programming puzzle. It took two days of thinking and pushed by perseverence. The first intuition for a potential solution was to use a bipartite matching algorithm. This led me down the rabit hole of maximal matching algorithsm and specifically the hungarian algorithm. After playing around with it a bit, I realized that it wouldn't work because it didn't guarantee that the nominee with the most vote in a given position would win. After a lot of hard thinking, some modelling using the bipartite graph led to a pretty good solution.

Favorite Pieces of Code

Screenshots

Login/Sign up page

All elections list page

Election nomination page

Voting page

Results page

Profile page to change passwords

Blockchain Explorer page

Admin Dashboard

Create new election form

Resolve elections that are on hold

voting-chain's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

voting-chain's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.