Skip to content

Latest commit

 

History

History
502 lines (401 loc) · 13 KB

File metadata and controls

502 lines (401 loc) · 13 KB

🏗️ Architecture Documentation

System Overview

The Blockchain Voting System is a secure, immutable voting platform built on blockchain principles. It ensures vote integrity through cryptographic hashing, prevents double-voting through comprehensive validation, and maintains a tamper-proof audit trail.

Core Components

1. Vote Class (Vote.h, Vote.cpp)

Purpose: Represents a single immutable vote record.

Responsibilities:

  • Store voter temporary ID (anonymous identifier)
  • Store candidate selection
  • Record timestamp of vote casting
  • Provide validation of vote fields
  • Serialize vote data for hashing

Key Design Decisions:

  • Immutability: Once created, votes cannot be modified
  • Timestamps are automatic to prevent manipulation
  • Validation occurs at construction time

Public Interface:

class Vote {
public:
    Vote(const std::string& voterId, const std::string& candidateName);
    std::string getVoterTempID() const;
    std::string getCandidate() const;
    std::time_t getTimestamp() const;
    bool isValid() const;
    std::string toString() const;
};

2. Block Class (Block.h, Block.cpp)

Purpose: Container for votes with cryptographic linking capability.

Responsibilities:

  • Store multiple votes in a transaction batch
  • Link to previous block via hash reference
  • Calculate and maintain SHA-256 hash
  • Validate block integrity
  • Prevent duplicate voters within block

Key Design Decisions:

  • Hash recalculation on any data change
  • Genesis block factory method for chain initialization
  • Automatic hash chaining

Hash Calculation:

Hash = SHA256(index + previousHash + timestamp + votes)

Public Interface:

class Block {
public:
    Block(int idx, const std::string& prevHash);
    bool addVote(const Vote& vote);
    bool hasVoter(const std::string& voterTempID) const;
    bool isValid() const;
    std::string getHash() const;
    static Block createGenesisBlock();
};

3. Blockchain Class (Blockchain.h, Blockchain.cpp)

Purpose: Manages the complete blockchain and enforces voting rules.

Responsibilities:

  • Maintain chain of blocks in correct order
  • Validate new blocks before addition
  • Detect duplicate voters across entire chain
  • Verify chain integrity
  • Provide statistics and analytics
  • Integrate with DeadBlock for rejected vote tracking

Key Design Decisions:

  • Genesis block auto-created on initialization
  • Chain validation checks both hash integrity and linking
  • Duplicate detection scans entire history
  • DeadBlock integration for transparency

Validation Process:

  1. Validate vote fields (non-empty, proper format)
  2. Check for duplicate voter ID across all blocks
  3. Check for duplicate voter ID in pending block
  4. Add vote if all checks pass

Public Interface:

class Blockchain {
public:
    Blockchain();
    void addBlock(Block newBlock);
    bool addVoteToPendingBlock(Block& pendingBlock, const Vote& vote);
    bool hasVoterVoted(const std::string& voterTempID) const;
    bool isChainValid() const;
    int getTotalVotes() const;
    const DeadBlock& getDeadBlock() const;
};

4. SHA256Helper Class (SHA256Helper.h, SHA256Helper.cpp)

Purpose: Cryptographic hashing utility using OpenSSL.

Responsibilities:

  • Compute SHA-256 hashes from string input
  • Convert binary hash to hexadecimal representation
  • Provide consistent hashing interface

Key Design Decisions:

  • Static methods for utility functionality
  • Uses OpenSSL for industry-standard implementation
  • Returns 64-character hex strings (256 bits)

Security Properties:

  • Deterministic: Same input always produces same output
  • One-way: Cannot reverse hash to get original data
  • Collision-resistant: Extremely unlikely two inputs produce same hash
  • Avalanche effect: Tiny input change produces completely different hash

5. VoteValidator Class (VoteValidator.h, VoteValidator.cpp)

Purpose: Centralized validation rules and error reporting.

Responsibilities:

  • Validate voter ID format and length
  • Validate candidate name format and length
  • Provide detailed error messages
  • Enforce security constraints

Validation Rules:

  • Voter ID: 3-50 characters, alphanumeric + hyphen/underscore
  • Candidate: 2-100 characters
  • No whitespace-only strings
  • No special characters that could cause injection attacks

Public Interface:

struct ValidationResult {
    bool isValid;
    std::string errorMessage;
};

class VoteValidator {
public:
    static ValidationResult validateVoterID(const std::string& voterID);
    static ValidationResult validateCandidate(const std::string& candidate);
    static ValidationResult validateVote(const std::string& voterID, 
                                         const std::string& candidate);
};

6. DeadBlock Class (DeadBlock.h, DeadBlock.cpp)

Purpose: Audit trail for rejected votes with detailed metadata.

Responsibilities:

  • Track invalid votes (format/field errors)
  • Track duplicate votes (double-voting attempts)
  • Categorize rejections with detailed reasons
  • Provide export capabilities (CSV, JSON)
  • Enable transparency and debugging

Rejection Categories:

  • Empty voter ID/candidate
  • Whitespace-only fields
  • Length violations (too short/long)
  • Invalid characters
  • Cross-chain duplicates
  • Same-block duplicates

Public Interface:

class DeadBlock {
public:
    DeadBlock();
    void logInvalidVote(const std::string& voterTempID,
                       const std::string& candidate,
                       RejectionReason reason,
                       const std::string& message = "");
    void logDuplicateVote(const std::string& voterTempID,
                         const std::string& candidate,
                         RejectionReason reason,
                         const std::string& message = "");
    std::string toCSV() const;
    std::string toJSON() const;
};

7. Validator Class (Validator.h, Validator.cpp) ⭐ NEW

Purpose: Represents an authorized validator in Proof of Authority network.

Responsibilities:

  • Store validator identity and credentials
  • Generate digital signatures for blocks
  • Track validation statistics
  • Support active/inactive status

Key Design Decisions:

  • Simulated digital signatures using SHA-256 (upgradeable to ECDSA)
  • Public key for signature verification
  • Statistics tracking for accountability

Public Interface:

class Validator {
public:
    Validator(const std::string& id, const std::string& name, 
              const std::string& publicKey);
    std::string signBlock(const std::string& blockHash) const;
    static bool verifySignature(const std::string& blockHash,
                               const std::string& signature,
                               const std::string& publicKey);
    void setActive(bool active);
    void incrementBlocksValidated();
};

8. ConsensusPoA Class (ConsensusPoA.h, ConsensusPoA.cpp) ⭐ NEW

Purpose: Proof of Authority consensus engine for multi-signature block approval.

Responsibilities:

  • Manage authorized validators (registration, removal)
  • Accept block submissions for consensus
  • Collect validator signatures
  • Enforce minimum approval threshold (3/4)
  • Finalize approved blocks
  • Reject blocks with insufficient consensus
  • Maintain audit trail of all approvals

Key Design Decisions:

  • 4 validators with 3-approval threshold (75% consensus)
  • Multi-signature approval prevents single point of failure
  • Pending blocks await consensus before finalization
  • Complete transparency with audit logs

Consensus Workflow:

  1. Block submitted for consensus
  2. Validators independently review and sign
  3. Signatures collected (requires 3/4)
  4. Block finalized if threshold reached
  5. Block rejected if insufficient signatures

Public Interface:

class ConsensusPoA {
public:
    ConsensusPoA(int minApprovals = 3);
    void registerValidator(const Validator& validator);
    bool submitBlockForConsensus(const Block& block);
    ConsensusResult addValidatorSignature(const std::string& blockHash,
                                         const std::string& validatorID);
    bool finalizeBlock(const std::string& blockHash);
    bool hasReachedConsensus(const std::string& blockHash) const;
    int getTotalBlocksApproved() const;
    int getTotalBlocksRejected() const;
};

Data Flow

Vote Submission Flow

1. User creates Vote object
   ↓
2. Vote.isValid() checks fields
   ↓
3. Blockchain.addVoteToPendingBlock() called
   ↓
4. VoteValidator validates format
   ↓
5. Blockchain.hasVoterVoted() scans chain
   ↓
6. Block.hasVoter() checks pending block
   ↓
7. Block.addVote() adds to pending block
   ↓
8. Block hash recalculated
   ↓
9. Block added to blockchain
   ↓
10. Chain validation confirms integrity

Chain Validation Flow

1. For each block (starting from index 1):
   ↓
2. Check block's stored hash matches calculated hash
   ↓
3. Check block's previousHash matches actual previous block's hash
   ↓
4. Genesis block hash validated separately
   ↓
5. Return true if all checks pass

Security Model

Immutability Guarantees

  1. Vote Immutability: Votes use const methods and private members
  2. Block Immutability: Hash changes if any data changes
  3. Chain Immutability: Modifying old blocks breaks hash chain
  4. Cryptographic Proof: SHA-256 ensures tamper detection

Attack Resistance

Double-Voting Prevention:

  • Cross-block scan ensures one vote per voter ID
  • O(n*m) complexity trade-off for guaranteed accuracy
  • Future optimization: Hash set for O(1) lookup

Data Tampering Detection:

  • Any modification changes block hash
  • Hash chain breaks immediately
  • isChainValid() detects tampering

Invalid Vote Prevention:

  • Field validation rejects empty/malformed votes
  • Length constraints prevent buffer overflows
  • Character restrictions prevent injection attacks

Performance Characteristics

Time Complexity

Operation Complexity Notes
Add Vote O(n*m) Scans chain for duplicates
Block Validation O(k) k = votes in block
Chain Validation O(n*m) Validates all blocks
Hash Calculation O(d) d = data size

Where:

  • n = number of blocks
  • m = average votes per block
  • k = votes in specific block
  • d = total data in block

Space Complexity

Component Space Notes
Vote O(1) Fixed size per vote
Block O(m) m = votes in block
Blockchain O(n*m) Total votes in chain
Hash O(1) 64 bytes per hash

Design Patterns Used

1. Factory Pattern

Block Block::createGenesisBlock();
  • Encapsulates genesis block creation
  • Ensures consistent initialization

2. Value Object Pattern

class Vote {
    // Immutable once created
    const std::string voterTempID;
    const std::string candidate;
};
  • Votes are value objects
  • Equality based on content

3. Strategy Pattern

class VoteValidator {
    static ValidationResult validate(...);
};
  • Validation logic is pluggable
  • Easy to extend validation rules

4. Chain of Responsibility

validateFields() -> hasVoterVoted() -> hasVoter() -> addVote()
  • Multiple validation stages
  • Early exit on failure

Future Enhancements

1. Performance Optimization

  • Add hash set for O(1) voter lookup
  • Implement vote indexing
  • Add caching for frequent queries

2. Advanced Features

  • Proof of Work consensus
  • Merkle tree for efficient verification
  • Smart contracts for automated rules
  • Multi-signature authorization

3. Scalability

  • Sharding for large-scale elections
  • P2P network layer
  • Distributed consensus
  • Load balancing

4. Security Enhancements

  • Digital signatures for voter authentication
  • Zero-knowledge proofs for privacy
  • Threshold cryptography
  • Secure enclaves for key management

Testing Strategy

Unit Tests

  • Vote validation
  • Block hash calculation
  • Chain validation
  • Duplicate detection

Integration Tests

  • Multi-block scenarios
  • Cross-block duplicate detection
  • Chain integrity after tampering

Security Tests

  • Invalid vote rejection
  • Duplicate vote prevention
  • Tamper detection
  • Hash collision resistance

Deployment Considerations

Production Requirements

  1. OpenSSL: Must be installed and accessible
  2. C++11 Compiler: GCC 4.8+, Clang 3.3+, MSVC 2015+
  3. Memory: ~100MB for 100,000 votes
  4. Storage: ~1GB for 1 million votes

Configuration

  • Block size: Configurable votes per block
  • Validation rules: Customizable in VoteValidator
  • Hash algorithm: Swappable (currently SHA-256)

Maintenance

Code Organization

  • Header files (include/): Public interfaces
  • Source files (src/): Implementation details
  • Main file (main.cpp): Test and demonstration code

Versioning

  • Current version: 2.0.0
  • Semantic versioning: MAJOR.MINOR.PATCH
  • Git tags for releases

Documentation

  • Code comments: Explain "why" not "what"
  • README: User-facing documentation
  • ARCHITECTURE: This document
  • COMPLEXITY_ANALYSIS: Performance details