Decentralized voting platform with biometric verification and on-chain auditability
An end-to-end voting solution that combines Ethereum smart contracts with face and fingerprint authentication.
- Overview
- Key Features
- System Architecture
- Technology Stack
- Project Structure
- Prerequisites
- Installation and Setup
- Hardware Requirements
- API Reference
- Smart Contract Functions
- Usage Guide
- Security Considerations
- Troubleshooting
- Contributing
- Authors
- Acknowledgments
The Blockchain Biometric Voting System is an electronic voting platform designed for integrity, transparency, and strong voter verification.
Core guarantees:
- Immutability: Votes are recorded on Ethereum and cannot be altered retroactively.
- Transparency: Vote counts and election state are verifiable on-chain.
- Security: Dual biometric verification (face and fingerprint) reduces impersonation risk.
- Privacy: Individual choices are not exposed while maintaining verifiable outcomes.
- Accessibility: Supports single-biometric flows for voters with disabilities.
The system is suitable for controlled pilots, institutional elections, and scalable production-oriented deployments with additional hardening.
- Face Recognition: 128-dimensional face encoding pipeline.
- Fingerprint Verification: Sensor-driven fingerprint capture using Arduino with R307/R305.
- Accessibility Support: Optional single-biometric onboarding for eligible users.
- Smart Contracts: Election lifecycle and voting logic implemented in Solidity.
- ThirdWeb SDK: Frontend contract interactions and transaction flow management.
- On-Chain State: Election, voter, and candidate state managed through contract methods.
- Next.js 14: Server-rendered React framework.
- TypeScript: Safer development with static typing.
- Bootstrap 5: Responsive UI components.
- Chart.js: Live vote and election visualization.
- Flask API: Endpoints for biometric workflows and hardware orchestration.
- Face Processing: OpenCV +
face_recognitionstack. - Serial Communication: Arduino interface through PySerial.
┌─────────────────────────────────────────────────────────────────────────────┐
│ USER INTERFACE │
│ (Next.js + TypeScript) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │
│ │ Register │ │ Admin │ │ Verification │ │ Results │ │
│ │ Page │ │ Panel │ │ Page │ │ Page │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └─────┬─────┘ │
└─────────┼───────────────────┼───────────────────┼───────────────────┼───────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ THIRDWEB SDK │
│ (Blockchain Communication Layer) │
└─────────────────────────────────────────────────────────────────────────────┘
│ │
▼ ▼
┌─────────────────────────────┐ ┌─────────────────────────────────────────┐
│ ETHEREUM BLOCKCHAIN │ │ PYTHON BACKEND │
│ (BiometricVotingSystem) │ │ (Flask) │
│ │ │ │
│ • Voter Registration │ │ • Face Recognition API │
│ • Candidate Registration │ │ • Fingerprint Controller │
│ • Vote Casting │ │ • OpenCV + dlib │
│ • Election Management │ │ • PySerial │
│ • Result Declaration │ │ │
└─────────────────────────────┘ └───────────────────────────┬─────────────┘
│
▼
┌─────────────────────────────────────────┐
│ ARDUINO MICROCONTROLLER │
│ (C++ Code) │
│ │
│ • Register fingerprint │
│ • Verify fingerprint │
│ • Delete fingerprint │
│ │
│ R307/R305 Fingerprint Sensor │
└─────────────────────────────────────────┘
| Technology | Version | Purpose |
|---|---|---|
| Next.js | 14.2.x | React framework with SSR |
| TypeScript | 5.x | Type-safe JavaScript |
| React | 18.3.x | UI library |
| Bootstrap | 5.3.x | CSS framework |
| ThirdWeb SDK | 5.70.x | Blockchain integration |
| Chart.js | 4.4.x | Vote visualization |
| Axios | 1.7.x | HTTP client |
| pdf-lib | 1.17.x | PDF generation |
| Technology | Version | Purpose |
|---|---|---|
| Python | 3.8+ | Runtime |
| Flask | Latest | Web framework |
| Flask-CORS | Latest | CORS support |
| face_recognition | Latest | Face encoding and comparison |
| OpenCV (cv2) | Latest | Image processing |
| NumPy | Latest | Numerical operations |
| PySerial | Latest | Arduino communication |
| Technology | Version | Purpose |
|---|---|---|
| Solidity | 0.8.19 | Smart contract language |
| Ethereum | - | Blockchain network |
| ThirdWeb | - | Deployment and interaction tooling |
| Technology | Version | Purpose |
|---|---|---|
| Arduino | C++ | Microcontroller programming |
| Adafruit Fingerprint Library | Latest | Sensor communication |
| SoftwareSerial | - | Serial emulation |
| R307/R305 Sensor | - | Fingerprint capture |
Blockchain-Voting-System/
│
├── Arduino c++/
│ └── c/
│ └── c.ino # Arduino fingerprint sensor code
│
├── blockchain solidity/
│ ├── blockchain.sol # Main smart contract
│ └── artifacts/ # Compiled contract artifacts
│
├── next.js frontend/
│ ├── src/
│ │ └── app/
│ │ ├── admin/ # Admin panel page
│ │ ├── register/ # Voter registration page
│ │ ├── verification/ # Vote verification page
│ │ └── page.tsx # Home page
│ ├── package.json # Frontend dependencies
│ ├── tsconfig.json # TypeScript configuration
│ └── next.config.mjs # Next.js configuration
│
├── python backend/
│ ├── app.py # Main Flask application
│ ├── face.py # Face recognition utilities
│ ├── finger.py # Fingerprint controller
│ └── requirements.txt # Python dependencies
│
└── README.md
| Software | Version | Download Link |
|---|---|---|
| Node.js | 18.x or higher | nodejs.org |
| Python | 3.8 or higher | python.org |
| Arduino IDE | 2.x | arduino.cc |
| Git | Latest | git-scm.com |
| Visual Studio Build Tools | 2019+ | visualstudio.microsoft.com |
| CMake | Latest | cmake.org |
Important
face_recognition depends on dlib, which requires C++ build tools.
Windows
pip install dlib
pip install face_recognitionLinux
sudo apt-get update
sudo apt-get install build-essential cmake libgtk-3-dev libboost-all-dev
pip install dlib face_recognitionmacOS
brew install cmake boost
pip install dlib face_recognitionConnect the R307/R305 Fingerprint Sensor to Arduino Uno/Nano:
| Sensor Pin | Arduino Pin | Wire Color (Typical) |
|---|---|---|
| VCC (Red) | 5V | Red |
| GND (Black) | GND | Black |
| TX (Green) | Pin 2 (RX) | Green |
| RX (White) | Pin 3 (TX) | White |
Warning
Sensor logic is typically 3.3V. Use a level shifter for long-term reliability.
- Install Arduino IDE.
- Install
Adafruit Fingerprint Sensor Library. - Open and upload:
cd "Arduino c++/c"
- Verify serial output at 115200 baud:
{"status":"ready","message":"Fingerprint sensor connected"}
| Command | Description |
|---|---|
REGISTER:<id> |
Register fingerprint with ID |
VERIFY |
Verify fingerprint and return matched ID |
DELETE:<id> |
Delete fingerprint by ID |
DELETEALL |
Delete all stored fingerprints |
DOWNLOAD |
Download fingerprint template |
cd "python backend"
python -m venv venvActivate environment:
- Windows:
venv\Scripts\activate
- Linux/macOS:
source venv/bin/activate
Install dependencies:
pip install -r requirements.txtrequirements.txt:
flask
flask-cors
face_recognition
opencv-python
numpy
pyserialCreate .env in python backend/:
FLASK_APP=app.py
FLASK_ENV=development
FLASK_DEBUG=1
FINGERPRINT_PORT=COM3Run backend:
python app.pyDefault backend URL: http://localhost:5000
- Create ThirdWeb account and connect wallet.
- Deploy
blockchain solidity/blockchain.sol. - Set frontend env values in
next.js frontend/.env.local:
NEXT_PUBLIC_THIRDWEB_CLIENT_ID=your_client_id
NEXT_PUBLIC_CONTRACT_ADDRESS=your_deployed_contract_addressnpm install --save-dev hardhat
npx hardhat init
npx hardhat compile
npx hardhat run scripts/deploy.js --network sepoliacd "next.js frontend"
npm install
npm run devCreate next.js frontend/.env.local:
NEXT_PUBLIC_THIRDWEB_CLIENT_ID=your_thirdweb_client_id
NEXT_PUBLIC_CONTRACT_ADDRESS=0x_your_deployed_contract_address
NEXT_PUBLIC_API_URL=http://localhost:5000
NEXT_PUBLIC_CHAIN_ID=11155111Default frontend URL: http://localhost:3000
| Component | Specification |
|---|---|
| Model | R307 or R305 Optical Fingerprint Sensor |
| Voltage | 3.3V - 6V DC |
| Current | < 120mA |
| Interface | UART (TTL) |
| Baud Rate | 9600 - 115200 (default: 57600) |
| Storage | 162-500 templates |
| FAR | < 0.001% |
| FRR | < 1.0% |
| Component | Specification |
|---|---|
| Model | Arduino Uno R3 / Nano / Mega |
| Microcontroller | ATmega328P / ATmega2560 |
| Digital I/O | 14-54 pins |
| USB | Type-B / Mini-B |
| Component | Specification |
|---|---|
| Resolution | Minimum 720p (1080p recommended) |
| Frame Rate | 30 FPS |
| Connection | USB 2.0 or higher |
Encodes face image to a 128-dimensional vector.
curl -X POST http://localhost:5000/api/encode_face \
-F "file=@face_image.jpg"Compares two face encodings.
Request:
{
"encoding1": [0.123, -0.456, "..."],
"encoding2": [0.789, -0.012, "..."],
"threshold": 0.6
}Response:
{
"success": true,
"data": {
"similarity_score": 0.85,
"is_match": true,
"threshold": 0.6,
"face_distance": 0.15
}
}Initialize sensor connection.
Register fingerprint for a voter.
Verify fingerprint and return voter identity match.
Delete fingerprint template for a voter.
Delete all templates.
Restart fingerprint service.
| Function | Access | Description |
|---|---|---|
startElection() |
Public | Move from registration to voting |
endElection() |
Public | End voting and compute result |
newElection() |
Public | Reset election cycle |
getElectionStatus() |
View | Current election phase |
| Function | Access | Description |
|---|---|---|
registerVoter(...) |
Registration phase | Register voter with biometric references |
removeVoter(voterId) |
Registration phase | Remove voter |
getAllVoters() |
View | List all voters |
getTotalVoterCount() |
View | Voter count |
| Function | Access | Description |
|---|---|---|
registerCandidate(name) |
Registration phase | Register candidate |
removeCandidate(candidateId) |
Registration phase | Remove candidate |
getAllCandidates() |
View | List all candidates |
getTotalCandidateCount() |
View | Candidate count |
| Function | Access | Description |
|---|---|---|
castVote(voterId, candidateId) |
Voting phase | Cast vote |
getVoteCounts() |
View | Current vote totals |
getVoterVotingStatus() |
View | Check voting status |
getWinner() |
Post-election | Return winner |
- Deploy smart contract.
- Start backend service.
- Connect and validate fingerprint sensor.
- Open admin panel (
/admin). - Register candidates.
- Start election.
- End election and publish results.
- During registration:
- Open
/register - Submit voter details
- Complete face capture
- Complete fingerprint capture
- Open
- During voting:
- Open
/verification - Complete biometric verification
- Select candidate and cast vote
- Open
Single-biometric registration is supported where required:
- Face only
- Fingerprint only
Note
At least one biometric credential is required.
- Face data is processed as embeddings, not raw images for identity matching.
- Fingerprint templates remain on sensor hardware.
- On-chain storage should avoid raw biometric material.
- Election actions are auditable through transaction history.
- Contract guards restrict invalid state transitions.
- Double voting is prevented by contract logic.
- Enable strict input validation.
- Restrict CORS to trusted origins in production.
- Protect secrets (wallet keys, API credentials, RPC endpoints).
Caution
Use HTTPS in production and perform independent security audits before real-world deployment.
| Issue | Action |
|---|---|
| Sensor not detected | Verify wiring and serial port |
| Communication failure | Validate baud rate and cable quality |
| Poor capture quality | Clean sensor surface |
| Enrollment failure | Retry with correct finger placement |
| Issue | Action |
|---|---|
| Face not detected | Improve lighting and camera angle |
| Multiple faces detected | Ensure one subject in frame |
| dlib build fails | Install required C++ build toolchain |
| Low similarity score | Retake image in stable lighting |
| Issue | Action |
|---|---|
| Transaction failure | Check wallet funds and gas settings |
| Contract call error | Verify deployed address and chain ID |
| ThirdWeb errors | Validate client ID and network configuration |
| Issue | Action |
|---|---|
| CORS errors | Confirm Flask-CORS configuration |
| Port conflicts | Change backend/frontend port |
| Missing modules | Reinstall dependencies in active environment |
Contributions are welcome.
- Fork repository.
- Create feature branch:
git checkout -b feature/your-feature-name
- Commit changes.
- Push branch.
- Open pull request.
- TypeScript/JavaScript: ESLint + Prettier
- Python: PEP 8
- Solidity: Solidity style guide
- Arduino C++: Arduino conventions
- Rahul — Initial development — @rahulratho15
- Contact: rahulrathnavel15@gmail.com
- ThirdWeb — blockchain development platform
- Adafruit — fingerprint tooling
- dlib — face recognition backend
- OpenZeppelin — smart contract security patterns