diff --git a/cli/genesis_cli.py b/cli/genesis_cli.py
index 3ed98900..9b4577aa 100755
--- a/cli/genesis_cli.py
+++ b/cli/genesis_cli.py
@@ -13,25 +13,43 @@ from pathlib import Path
def handle_genesis_init(args):
"""Initialize genesis block and wallet"""
- script_path = Path("/opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py")
+ # Use new genesis-init.py script for basic genesis initialization
+ new_script_path = Path("/opt/aitbc/scripts/utils/genesis-init.py")
+ old_script_path = Path("/opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py")
- if not script_path.exists():
- print(f"Error: Genesis generation script not found: {script_path}")
+ # Prefer new script if it exists and we're not doing wallet creation
+ if new_script_path.exists() and not args.create_wallet:
+ script_path = new_script_path
+ use_new_script = True
+ elif old_script_path.exists():
+ script_path = old_script_path
+ use_new_script = False
+ else:
+ print(f"Error: Genesis generation script not found")
return 1
- cmd = [sys.executable, str(script_path), "--chain-id", args.chain_id]
-
- if args.create_wallet:
- cmd.append("--create-wallet")
- if args.password:
- cmd.extend(["--password", args.password])
- if args.proposer:
- cmd.extend(["--proposer", args.proposer])
- if args.force:
- cmd.append("--force")
- if args.register_service:
- cmd.append("--register-service")
- cmd.extend(["--service-url", args.service_url])
+ if use_new_script:
+ # Use new simpler script
+ cmd = [sys.executable, str(script_path), "--chain-id", args.chain_id]
+ if args.proposer:
+ cmd.extend(["--proposer", args.proposer])
+ else:
+ print("Error: --proposer is required for genesis initialization")
+ return 1
+ else:
+ # Use old comprehensive script for wallet creation
+ cmd = [sys.executable, str(script_path), "--chain-id", args.chain_id]
+ if args.create_wallet:
+ cmd.append("--create-wallet")
+ if args.password:
+ cmd.extend(["--password", args.password])
+ if args.proposer:
+ cmd.extend(["--proposer", args.proposer])
+ if args.force:
+ cmd.append("--force")
+ if args.register_service:
+ cmd.append("--register-service")
+ cmd.extend(["--service-url", args.service_url])
try:
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
diff --git a/cli/unified_cli.py b/cli/unified_cli.py
index eb1e3f80..d4aaade2 100755
--- a/cli/unified_cli.py
+++ b/cli/unified_cli.py
@@ -645,25 +645,43 @@ def handle_genesis_init(args):
import sys
from pathlib import Path
- script_path = Path("/opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py")
+ # Use new genesis-init.py script for basic genesis initialization
+ new_script_path = Path("/opt/aitbc/scripts/utils/genesis-init.py")
+ old_script_path = Path("/opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py")
- if not script_path.exists():
- print(f"Error: Genesis generation script not found: {script_path}")
+ # Prefer new script if it exists and we're not doing wallet creation
+ if new_script_path.exists() and not args.create_wallet:
+ script_path = new_script_path
+ use_new_script = True
+ elif old_script_path.exists():
+ script_path = old_script_path
+ use_new_script = False
+ else:
+ print(f"Error: Genesis generation script not found")
return
- cmd = [sys.executable, str(script_path), "--chain-id", args.chain_id]
-
- if args.create_wallet:
- cmd.append("--create-wallet")
- if args.password:
- cmd.extend(["--password", args.password])
- if args.proposer:
- cmd.extend(["--proposer", args.proposer])
- if args.force:
- cmd.append("--force")
- if args.register_service:
- cmd.append("--register-service")
- cmd.extend(["--service-url", args.service_url])
+ if use_new_script:
+ # Use new simpler script
+ cmd = [sys.executable, str(script_path), "--chain-id", args.chain_id]
+ if args.proposer:
+ cmd.extend(["--proposer", args.proposer])
+ else:
+ print("Error: --proposer is required for genesis initialization")
+ return
+ else:
+ # Use old comprehensive script for wallet creation
+ cmd = [sys.executable, str(script_path), "--chain-id", args.chain_id]
+ if args.create_wallet:
+ cmd.append("--create-wallet")
+ if args.password:
+ cmd.extend(["--password", args.password])
+ if args.proposer:
+ cmd.extend(["--proposer", args.proposer])
+ if args.force:
+ cmd.append("--force")
+ if args.register_service:
+ cmd.append("--register-service")
+ cmd.extend(["--service-url", args.service_url])
try:
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
diff --git a/scripts/utils/genesis-init.py b/scripts/utils/genesis-init.py
new file mode 100755
index 00000000..14cebc8e
--- /dev/null
+++ b/scripts/utils/genesis-init.py
@@ -0,0 +1,206 @@
+#!/usr/bin/env python3
+"""
+Genesis Block Initialization Script
+
+This script creates genesis blocks and initializes accounts for AITBC chains.
+It can be used to set up new chains or re-initialize existing ones.
+
+Usage:
+ python scripts/utils/genesis-init.py --chain-id ait-testnet --proposer
--balance
+"""
+
+import argparse
+import json
+import sqlite3
+import sys
+from datetime import datetime
+from pathlib import Path
+from typing import Optional, List, Dict, Any
+
+
+def compute_genesis_hash(height: int, parent_hash: str, timestamp: datetime) -> str:
+ """Compute genesis block hash (simplified - in production use proper crypto)"""
+ # For now, use a deterministic hash based on the genesis data
+ data = f"{height}:{parent_hash}:{timestamp.isoformat()}:genesis"
+ import hashlib
+ return hashlib.sha256(data.encode()).hexdigest()
+
+
+def create_genesis_json(
+ chain_id: str,
+ proposer: str,
+ balance: int,
+ output_path: Optional[Path] = None,
+ chain_type: str = "testnet"
+) -> Path:
+ """Create genesis.json file for a chain"""
+
+ timestamp = datetime(2025, 1, 1, 0, 0, 0)
+ genesis_hash = compute_genesis_hash(0, "0x00", timestamp)
+
+ genesis_data = {
+ "chain_id": chain_id,
+ "block": {
+ "height": 0,
+ "hash": genesis_hash,
+ "parent_hash": "0x00",
+ "proposer": proposer,
+ "timestamp": timestamp.isoformat(),
+ "tx_count": 0,
+ "chain_id": chain_id,
+ "state_root": "0x00",
+ "metadata": {
+ "chain_type": chain_type,
+ "purpose": "testing" if chain_type == "testnet" else "production",
+ "consensus_algorithm": "poa"
+ }
+ },
+ "allocations": [
+ {
+ "address": proposer,
+ "balance": balance,
+ "nonce": 0
+ }
+ ]
+ }
+
+ if output_path is None:
+ output_path = Path(f"/var/lib/aitbc/data/{chain_id}/genesis.json")
+
+ output_path.parent.mkdir(parents=True, exist_ok=True)
+
+ with open(output_path, 'w') as f:
+ json.dump(genesis_data, f, indent=2)
+
+ print(f"Created genesis.json at {output_path}")
+ return output_path
+
+
+def initialize_database(
+ chain_id: str,
+ proposer: str,
+ balance: int,
+ db_path: Optional[Path] = None
+) -> None:
+ """Initialize database with genesis block and account"""
+
+ if db_path is None:
+ db_path = Path(f"/var/lib/aitbc/data/{chain_id}/chain.db")
+
+ db_path.parent.mkdir(parents=True, exist_ok=True)
+
+ conn = sqlite3.connect(db_path)
+ cursor = conn.cursor()
+
+ # Create tables (simplified schema - matches SQLModel models)
+ cursor.execute("""
+ CREATE TABLE IF NOT EXISTS block (
+ id INTEGER NOT NULL,
+ chain_id VARCHAR NOT NULL,
+ height INTEGER NOT NULL,
+ hash VARCHAR NOT NULL,
+ parent_hash VARCHAR NOT NULL,
+ proposer VARCHAR NOT NULL,
+ timestamp DATETIME NOT NULL,
+ tx_count INTEGER NOT NULL,
+ state_root VARCHAR,
+ block_metadata VARCHAR,
+ PRIMARY KEY (id),
+ CONSTRAINT uix_block_chain_height UNIQUE (chain_id, height)
+ )
+ """)
+
+ cursor.execute("""
+ CREATE TABLE IF NOT EXISTS account (
+ chain_id VARCHAR NOT NULL,
+ address VARCHAR NOT NULL,
+ balance INTEGER NOT NULL,
+ nonce INTEGER NOT NULL,
+ updated_at DATETIME NOT NULL,
+ PRIMARY KEY (chain_id, address)
+ )
+ """)
+
+ # Create indexes
+ cursor.execute("CREATE INDEX IF NOT EXISTS ix_block_chain_id ON block (chain_id)")
+ cursor.execute("CREATE INDEX IF NOT EXISTS ix_block_height ON block (height)")
+ cursor.execute("CREATE UNIQUE INDEX IF NOT EXISTS ix_block_hash ON block (hash)")
+
+ # Check if genesis block already exists
+ cursor.execute(
+ "SELECT hash FROM block WHERE chain_id=? AND height=0",
+ (chain_id,)
+ )
+ existing = cursor.fetchone()
+
+ if existing:
+ print(f"Genesis block already exists for chain {chain_id}")
+ conn.close()
+ return
+
+ # Insert genesis block
+ timestamp = datetime(2025, 1, 1, 0, 0, 0)
+ genesis_hash = compute_genesis_hash(0, "0x00", timestamp)
+
+ cursor.execute(
+ """
+ INSERT INTO block (chain_id, height, hash, parent_hash, proposer, timestamp, tx_count, state_root)
+ VALUES (?, 0, ?, ?, ?, ?, 0, ?)
+ """,
+ (chain_id, genesis_hash, "0x00", proposer, timestamp.isoformat(), "0x00")
+ )
+
+ # Insert account with initial balance
+ cursor.execute(
+ """
+ INSERT INTO account (chain_id, address, balance, nonce, updated_at)
+ VALUES (?, ?, ?, ?, ?)
+ """,
+ (chain_id, proposer, balance, 0, timestamp.isoformat())
+ )
+
+ conn.commit()
+ conn.close()
+
+ print(f"Initialized database for chain {chain_id}")
+ print(f"Genesis block hash: {genesis_hash}")
+ print(f"Account {proposer} balance: {balance}")
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Initialize genesis block for AITBC chain")
+ parser.add_argument("--chain-id", required=True, help="Chain ID (e.g., ait-testnet)")
+ parser.add_argument("--proposer", required=True, help="Proposer address for genesis block")
+ parser.add_argument("--balance", type=int, default=1000000000, help="Initial balance (default: 1,000,000,000)")
+ parser.add_argument("--chain-type", default="testnet", choices=["mainnet", "testnet"], help="Chain type")
+ parser.add_argument("--db-path", help="Custom database path")
+ parser.add_argument("--genesis-path", help="Custom genesis.json path")
+ parser.add_argument("--skip-genesis", action="store_true", help="Skip creating genesis.json")
+ parser.add_argument("--skip-db", action="store_true", help="Skip database initialization")
+
+ args = parser.parse_args()
+
+ if not args.skip_genesis:
+ genesis_path = Path(args.genesis_path) if args.genesis_path else None
+ create_genesis_json(
+ chain_id=args.chain_id,
+ proposer=args.proposer,
+ balance=args.balance,
+ output_path=genesis_path,
+ chain_type=args.chain_type
+ )
+
+ if not args.skip_db:
+ db_path = Path(args.db_path) if args.db_path else None
+ initialize_database(
+ chain_id=args.chain_id,
+ proposer=args.proposer,
+ balance=args.balance,
+ db_path=db_path
+ )
+
+ print(f"\nGenesis initialization complete for chain {args.chain_id}")
+
+
+if __name__ == "__main__":
+ main()