CIA/e-voting-system/backend/init_blockchain.py
Alexis Bruneteau 7af375f8c0 feat: Add comprehensive logging to backend for debugging blockchain and startup
Add structured logging throughout the backend:
- logging_config.py: Centralized logging configuration with colored output
- main.py: Enhanced startup logging showing initialization progress
- init_blockchain.py: Detailed blockchain initialization logging
- services.py: Election creation logging

Logging features:
- Emoji prefixes for different log levels (INFO, DEBUG, ERROR, etc.)
- Color-coded output for better visibility
- Timestamp and module information
- Exception stack traces on errors
- Separate loggers for different modules

This helps debug:
- Backend startup sequence
- Database initialization
- Blockchain election recording
- Service operations
- Configuration issues
2025-11-07 03:06:38 +01:00

118 lines
4.3 KiB
Python

"""
Initialize blockchain with existing elections from database.
This module ensures that when the backend starts, all elections in the database
are recorded to the blockchain if they aren't already.
"""
import logging
from sqlalchemy.orm import Session
from . import models
from .blockchain_elections import elections_blockchain, record_election_to_blockchain
from datetime import datetime
import json
logger = logging.getLogger(__name__)
def initialize_elections_blockchain(db: Session) -> None:
"""
Initialize the elections blockchain with all elections from database.
Called on backend startup to ensure all elections are immutably recorded.
Uses the elections_blockchain.blocks to check if an election is already recorded.
Args:
db: Database session
"""
logger.info("-" * 60)
logger.info("Blockchain Initialization Started")
logger.info("-" * 60)
try:
# Get all elections from database
elections = db.query(models.Election).all()
logger.info(f"Found {len(elections)} elections in database")
if not elections:
logger.warning("No elections to record to blockchain")
return
# Check which elections are already on blockchain
existing_election_ids = {block.election_id for block in elections_blockchain.blocks}
logger.info(f"Blockchain currently has {len(existing_election_ids)} elections")
# Record each election that isn't already on blockchain
recorded_count = 0
skipped_count = 0
for election in elections:
if election.id in existing_election_ids:
logger.debug(f" ⊘ Election {election.id} ({election.name}) already on blockchain")
skipped_count += 1
continue
try:
# Get candidates for this election
candidates = db.query(models.Candidate).filter(
models.Candidate.election_id == election.id
).all()
logger.debug(f" Recording election {election.id} with {len(candidates)} candidates")
candidates_data = [
{
"id": c.id,
"name": c.name,
"description": c.description or "",
"order": c.order or 0
}
for c in candidates
]
# Record to blockchain
block = record_election_to_blockchain(
election_id=election.id,
election_name=election.name,
election_description=election.description or "",
candidates=candidates_data,
start_date=election.start_date.isoformat(),
end_date=election.end_date.isoformat(),
is_active=election.is_active,
creator_id=0 # Database creation, no specific admin
)
logger.info(
f" ✓ Recorded election {election.id} ({election.name})\n"
f" Block #{block.index}, Hash: {block.block_hash[:16]}..., "
f"Candidates: {block.candidates_count}"
)
recorded_count += 1
except Exception as e:
logger.error(
f" ✗ Failed to record election {election.id} ({election.name}): {e}",
exc_info=True
)
logger.info(f"Recording summary: {recorded_count} new, {skipped_count} skipped")
# Verify blockchain integrity
logger.info(f"Verifying blockchain integrity ({len(elections_blockchain.blocks)} blocks)...")
if elections_blockchain.verify_chain_integrity():
logger.info(f"✓ Blockchain integrity verified successfully")
else:
logger.error("✗ Blockchain integrity check FAILED - possible corruption!")
logger.info("-" * 60)
logger.info(f"Blockchain Initialization Complete")
logger.info(f" Total blocks: {len(elections_blockchain.blocks)}")
logger.info(f" Chain valid: {elections_blockchain.verify_chain_integrity()}")
logger.info("-" * 60)
except Exception as e:
logger.error(
f"Blockchain initialization failed with error: {e}",
exc_info=True
)
raise