This is a secure, transparent voting application built on blockchain technology. The system leverages Ethereum smart contracts to ensure vote integrity and prevent tampering, while using a traditional database for user management and election data.
The application follows a layered architecture:
- Frontend: Deployed separately, interacts with the REST API
- REST API Layer: Spring Boot controllers handle HTTP requests
- Service Layer: Business logic implementation
- Data Access Layer: JPA repositories for database operations
- Blockchain Layer: Ethereum smart contracts via Web3j
- Database: PostgreSQL for user and election data
- Authentication: JWT tokens with OTP verification
- Voter: Represents a voter with personal information and blockchain wallet address
- Candidate: Represents a candidate in an election
- Election: Represents an election event with start/end dates and blockchain contract address
- Admin: Represents an administrator with management privileges
- VoterService: Handles voter registration, authentication, and voting operations
- AdminService: Handles administrative functions like election and candidate management
- VotingService: Interfaces with the blockchain voting contract
- OtpService: Manages OTP generation and email sending
- ElectionService: Manages election data in the database
- AuthController: Handles user authentication (voter and admin)
- VotersController: Provides endpoints for voters to view candidates and cast votes
- AdminController: Provides administrative endpoints for managing elections and candidates
- SimpleVote.sol: Ethereum smart contract that tracks votes and prevents double voting
POST /auth/vo/registration
Body: {
"email": "string",
"name": "string",
"phoneNumber": "string",
"voterAddress": "string", // Blockchain wallet address
"password": "string",
"age": "integer"
}
POST /auth/vo/verification
Body: {
"email": "string",
"otp": "string"
}
POST /auth/vo/login
Body: {
"email": "string",
"password": "string",
"otp": "string" // Optional
}
POST /auth/ad/login
Body: {
"email": "string",
"password": "string",
"otp": "string" // Optional
}
GET /api/v1/voter/{id}
GET /api/v1/voter/candidates
PATCH /api/v1/voter/updateVoter
Body: {
"id": "long",
"email": "string", // Optional
"name": "string", // Optional
"phoneNumber": "string", // Optional
"voterAddress": "string", // Optional
"password": "string", // Optional
"age": "integer" // Optional
}
PATCH /api/v1/voter/vote
Body: {
"contractAddress": "string",
"id": "string", // Candidate ID
"voterAddress": "string"
}
GET /api/v1/voter/getVotes/{contractAddress}
POST /api/v1/admin/createElection
Body: {
"electionName": "string",
"startDate": "datetime",
"endDate": "datetime"
}
PATCH /api/v1/admin/updateElection
Body: {
"id": "integer",
"electionName": "string", // Optional
"from": "datetime", // Optional, updates startDate
"to": "datetime", // Optional, updates endDate
"contractAddress": "string" // Optional
}
DELETE /api/v1/admin/deleteElection/{id}
POST /api/v1/admin/createCandidate
Body: {
"name": "string",
"partyName": "string",
"constituency": "string"
}
PATCH /api/v1/admin/updateCandidate
Body: {
"id": "integer",
"name": "string", // Optional
"partyName": "string", // Optional
"constituency": "string" // Optional
}
DELETE /api/v1/admin/deleteCandidate/{id}
GET /api/v1/admin/getVoters/{page}
GET /api/v1/admin/getVoter/{id}
GET /api/v1/admin/getVotesForAll/{contractAddress}
GET /api/v1/admin/getVotes
Body: {
"contractAddress": "string",
"candidateId": "string"
}
PATCH /api/v1/admin/updateAdmin
Body: {
"id": "long",
"email": "string", // Optional
"name": "string", // Optional
"phoneNumber": "string", // Optional
"password": "string" // Optional
}
The application uses the Web3j library to interact with Ethereum smart contracts. The SimpleVote.sol contract provides the core voting functionality:
vote(uint256 candidateId): Cast a vote for a candidategetVotes(uint256 candidateId): Get vote count for a candidatehasVoted(address voter): Check if an address has already voted
- Vote Tracking: Each candidate's votes are stored in a mapping
- Double Voting Prevention: Voter addresses are tracked to prevent multiple votes
- Transparency: All vote data is stored on the blockchain and can be verified
- Immutability: Once a vote is cast, it cannot be altered or deleted
The application uses PostgreSQL to store user and election data:
- id (Primary Key)
- name
- age
- hasVoted (boolean)
- isEnabled (boolean)
- email (unique)
- phoneNumber
- voterAddress (unique, blockchain wallet address)
- password (hashed)
- otp
- expiration
- id (Primary Key)
- name
- partyName
- constituency
- id (Primary Key)
- electionName
- startDate
- endDate
- contractAddress (unique)
- id (Primary Key)
- name
- email (unique)
- phoneNumber
- password (hashed)
- otp
- expiration
- Both voters and admins receive JWT tokens upon successful login
- Tokens are used to authenticate subsequent requests
- Two-factor authentication using email-based OTPs
- OTPs expire after 15 minutes
- OTPs are regenerated when needed
- Passwords are hashed using Spring Security's password encoder
- Secure storage in database
- Voters must be registered and verified
- Voters can only vote once per election
- Blockchain ensures vote integrity and prevents tampering
The application requires several environment variables to be set:
POSTGRES_NEON_PASSWORD: PostgreSQL database passwordPRIVATE_KEY: Ethereum wallet private key for contract interactionsGMAIL_APP_PASSWORD: Gmail app password for OTP email sending
These can be set in the passwords.env file.
- Set up a PostgreSQL database
- Configure environment variables in
passwords.env - Deploy the Ethereum smart contract (if not already deployed)
- Update
application.propertieswith correct RPC URL and contract address - Build the application:
./mvnw clean package - Run the application:
java -jar target/demo-0.0.1-SNAPSHOT.jar
- Spring Boot
- Web3j (Ethereum integration)
- PostgreSQL driver
- Spring Security
- Spring Data JPA
- Lombok
- Java Mail Sender