✅ Log Migration - Moved repository logs to /var/log/aitbc/repository-logs - Moved production logs to /var/log/aitbc/production - Updated all code references to use /var/log/aitbc - Updated systemd services to use system logs - Removed logs from git tracking - Updated .gitignore for log files - Created proper system log structure - Set proper permissions for system logs ✅ System Compliance - All logs now in /var/log/aitbc (FHS compliant) - No log files in repository - Proper system-wide log location - Centralized log management ✅ Service Updates - Production services use /var/log/aitbc/production - SystemD services use /var/log/aitbc - All code references updated to system paths - Services restart and test successfully 🚀 AITBC logging now follows proper system standards!
271 lines
9.3 KiB
Python
271 lines
9.3 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Production Blockchain Service - Simplified
|
|
Working blockchain implementation with persistence
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
import time
|
|
import logging
|
|
from pathlib import Path
|
|
from datetime import datetime
|
|
import hashlib
|
|
|
|
# Production logging
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format='%(asctime)s [%(levelname)s] %(name)s: %(message)s',
|
|
handlers=[
|
|
logging.FileHandler('/var/log/aitbc/production/blockchain/blockchain.log'),
|
|
logging.StreamHandler()
|
|
]
|
|
)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class Block:
|
|
"""Simple block implementation"""
|
|
|
|
def __init__(self, index: int, data: dict, previous_hash: str):
|
|
self.index = index
|
|
self.timestamp = time.time()
|
|
self.data = data
|
|
self.previous_hash = previous_hash
|
|
self.hash = self.calculate_hash()
|
|
|
|
def calculate_hash(self) -> str:
|
|
"""Calculate block hash"""
|
|
content = f"{self.index}{self.timestamp}{json.dumps(self.data, sort_keys=True)}{self.previous_hash}"
|
|
return hashlib.sha256(content.encode()).hexdigest()
|
|
|
|
def to_dict(self) -> dict:
|
|
"""Convert block to dictionary"""
|
|
return {
|
|
'index': self.index,
|
|
'timestamp': self.timestamp,
|
|
'data': self.data,
|
|
'previous_hash': self.previous_hash,
|
|
'hash': self.hash
|
|
}
|
|
|
|
class Transaction:
|
|
"""Simple transaction implementation"""
|
|
|
|
def __init__(self, from_address: str, to_address: str, amount: float, data: dict = None):
|
|
self.from_address = from_address
|
|
self.to_address = to_address
|
|
self.amount = amount
|
|
self.data = data or {}
|
|
self.timestamp = time.time()
|
|
self.tx_hash = self.calculate_hash()
|
|
|
|
def calculate_hash(self) -> str:
|
|
"""Calculate transaction hash"""
|
|
content = f"{self.from_address}{self.to_address}{self.amount}{json.dumps(self.data, sort_keys=True)}{self.timestamp}"
|
|
return hashlib.sha256(content.encode()).hexdigest()
|
|
|
|
def to_dict(self) -> dict:
|
|
"""Convert transaction to dictionary"""
|
|
return {
|
|
'from_address': self.from_address,
|
|
'to_address': self.to_address,
|
|
'amount': self.amount,
|
|
'data': self.data,
|
|
'timestamp': self.timestamp,
|
|
'tx_hash': self.tx_hash
|
|
}
|
|
|
|
class ProductionBlockchain:
|
|
"""Production-grade blockchain implementation"""
|
|
|
|
def __init__(self, node_id: str):
|
|
self.node_id = node_id
|
|
self.data_dir = Path(f'/var/lib/aitbc/data/blockchain/{node_id}')
|
|
self.data_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
# Initialize blockchain
|
|
self.chain = []
|
|
self.pending_transactions = []
|
|
self.balances = {}
|
|
|
|
# Load existing data if available
|
|
self._load_blockchain()
|
|
|
|
# Create genesis block if empty
|
|
if not self.chain:
|
|
self._create_genesis_block()
|
|
|
|
logger.info(f"Production blockchain initialized for node: {node_id}")
|
|
|
|
def _create_genesis_block(self):
|
|
"""Create genesis block"""
|
|
genesis_data = {
|
|
'type': 'genesis',
|
|
'node_id': self.node_id,
|
|
'message': 'AITBC Production Blockchain Genesis Block',
|
|
'timestamp': time.time()
|
|
}
|
|
|
|
genesis_block = Block(0, genesis_data, '0')
|
|
self.chain.append(genesis_block)
|
|
self._save_blockchain()
|
|
|
|
logger.info("Genesis block created")
|
|
|
|
def _load_blockchain(self):
|
|
"""Load existing blockchain data"""
|
|
chain_file = self.data_dir / 'blockchain.json'
|
|
balances_file = self.data_dir / 'balances.json'
|
|
|
|
try:
|
|
if chain_file.exists():
|
|
with open(chain_file, 'r') as f:
|
|
data = json.load(f)
|
|
|
|
# Load blocks
|
|
self.chain = []
|
|
for block_data in data.get('blocks', []):
|
|
block = Block(
|
|
block_data['index'],
|
|
block_data['data'],
|
|
block_data['previous_hash']
|
|
)
|
|
block.hash = block_data['hash']
|
|
block.timestamp = block_data['timestamp']
|
|
self.chain.append(block)
|
|
|
|
logger.info(f"Loaded {len(self.chain)} blocks")
|
|
|
|
if balances_file.exists():
|
|
with open(balances_file, 'r') as f:
|
|
self.balances = json.load(f)
|
|
logger.info(f"Loaded balances for {len(self.balances)} addresses")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Failed to load blockchain: {e}")
|
|
|
|
def _save_blockchain(self):
|
|
"""Save blockchain state"""
|
|
try:
|
|
chain_file = self.data_dir / 'blockchain.json'
|
|
balances_file = self.data_dir / 'balances.json'
|
|
|
|
# Save blocks
|
|
data = {
|
|
'blocks': [block.to_dict() for block in self.chain],
|
|
'last_updated': time.time(),
|
|
'node_id': self.node_id
|
|
}
|
|
|
|
with open(chain_file, 'w') as f:
|
|
json.dump(data, f, indent=2)
|
|
|
|
# Save balances
|
|
with open(balances_file, 'w') as f:
|
|
json.dump(self.balances, f, indent=2)
|
|
|
|
logger.debug(f"Blockchain saved to {chain_file}")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Failed to save blockchain: {e}")
|
|
|
|
def create_transaction(self, from_address: str, to_address: str, amount: float, data: dict = None):
|
|
"""Create and process a transaction"""
|
|
try:
|
|
transaction = Transaction(from_address, to_address, amount, data)
|
|
|
|
# Add to pending transactions
|
|
self.pending_transactions.append(transaction)
|
|
|
|
# Process transaction (simplified - no validation for demo)
|
|
self._process_transaction(transaction)
|
|
|
|
# Create new block if we have enough transactions
|
|
if len(self.pending_transactions) >= 1: # Create block for each transaction in production
|
|
self._create_block()
|
|
|
|
logger.info(f"Transaction processed: {transaction.tx_hash}")
|
|
return transaction.tx_hash
|
|
|
|
except Exception as e:
|
|
logger.error(f"Failed to create transaction: {e}")
|
|
raise
|
|
|
|
def _process_transaction(self, transaction: Transaction):
|
|
"""Process a transaction"""
|
|
# Initialize balances if needed
|
|
if transaction.from_address not in self.balances:
|
|
self.balances[transaction.from_address] = 10000.0 # Initial balance
|
|
if transaction.to_address not in self.balances:
|
|
self.balances[transaction.to_address] = 0.0
|
|
|
|
# Check balance (simplified)
|
|
if self.balances[transaction.from_address] >= transaction.amount:
|
|
self.balances[transaction.from_address] -= transaction.amount
|
|
self.balances[transaction.to_address] += transaction.amount
|
|
logger.info(f"Transferred {transaction.amount} from {transaction.from_address} to {transaction.to_address}")
|
|
else:
|
|
logger.warning(f"Insufficient balance for {transaction.from_address}")
|
|
|
|
def _create_block(self):
|
|
"""Create a new block"""
|
|
if not self.pending_transactions:
|
|
return
|
|
|
|
previous_hash = self.chain[-1].hash if self.chain else '0'
|
|
|
|
block_data = {
|
|
'transactions': [tx.to_dict() for tx in self.pending_transactions],
|
|
'node_id': self.node_id,
|
|
'block_reward': 10.0
|
|
}
|
|
|
|
new_block = Block(len(self.chain), block_data, previous_hash)
|
|
self.chain.append(new_block)
|
|
|
|
# Clear pending transactions
|
|
self.pending_transactions.clear()
|
|
|
|
# Save blockchain
|
|
self._save_blockchain()
|
|
|
|
logger.info(f"Block {new_block.index} created")
|
|
|
|
def get_balance(self, address: str) -> float:
|
|
"""Get balance for address"""
|
|
return self.balances.get(address, 0.0)
|
|
|
|
def get_blockchain_info(self) -> dict:
|
|
"""Get blockchain information"""
|
|
return {
|
|
'node_id': self.node_id,
|
|
'blocks': len(self.chain),
|
|
'pending_transactions': len(self.pending_transactions),
|
|
'total_addresses': len(self.balances),
|
|
'last_block': self.chain[-1].to_dict() if self.chain else None,
|
|
'total_balance': sum(self.balances.values())
|
|
}
|
|
|
|
if __name__ == '__main__':
|
|
node_id = os.getenv('NODE_ID', 'aitbc')
|
|
blockchain = ProductionBlockchain(node_id)
|
|
|
|
# Example transaction
|
|
try:
|
|
tx_hash = blockchain.create_transaction(
|
|
from_address='0xuser1',
|
|
to_address='0xuser2',
|
|
amount=100.0,
|
|
data={'type': 'payment', 'description': 'Production test transaction'}
|
|
)
|
|
print(f"Transaction created: {tx_hash}")
|
|
|
|
# Print blockchain info
|
|
info = blockchain.get_blockchain_info()
|
|
print(f"Blockchain info: {info}")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Production blockchain error: {e}")
|
|
sys.exit(1)
|