From 4f4fde985e190d214e8286e6fe3e197bac8c66d0 Mon Sep 17 00:00:00 2001 From: aitbc Date: Sat, 25 Apr 2026 18:58:20 +0200 Subject: [PATCH] refactor: replace SQLAlchemy with sqlite3 in genesis initialization and add genesis CLI commands Replaced SQLAlchemy ORM with direct sqlite3 queries in unified_genesis.py initialize_genesis_database function to simplify database operations and remove dependency on SQLModel Session. Added genesis command group to CLI with init, verify, and info subcommands for genesis block and wallet management. Implemented handlers for genesis operations including initialization, verification, and information display --- .../scripts/unified_genesis.py | 85 ++++---- cli/aitbc_cli.py | 185 ++++++++++++++++- cli/genesis_cli.py | 196 ++++++++++++++++++ cli/unified_cli.py | 187 ++++++++++++++++- 4 files changed, 611 insertions(+), 42 deletions(-) create mode 100755 cli/genesis_cli.py diff --git a/apps/blockchain-node/scripts/unified_genesis.py b/apps/blockchain-node/scripts/unified_genesis.py index fceb8994..8960e836 100644 --- a/apps/blockchain-node/scripts/unified_genesis.py +++ b/apps/blockchain-node/scripts/unified_genesis.py @@ -193,49 +193,60 @@ def save_genesis_json(genesis_block: Dict, allocations: List[Dict], genesis_path def initialize_genesis_database(genesis_block: Dict, allocations: List[Dict], db_path: Path): """Initialize blockchain database with genesis data""" + import sqlite3 + try: - engine = create_engine(f"sqlite:///{db_path}") - with Session(engine) as session: - # Check if genesis already exists - existing = session.exec( - select(Block).where(Block.height == 0).where(Block.chain_id == genesis_block["chain_id"]) - ).first() - - if existing: - print(f"⚠️ Genesis block already exists in database") - return False - - # Create genesis block - block = Block( - height=genesis_block["height"], - hash=genesis_block["hash"], - parent_hash=genesis_block["parent_hash"], - proposer=genesis_block["proposer"], - timestamp=datetime.fromisoformat(genesis_block["timestamp"]), - tx_count=genesis_block["tx_count"], - chain_id=genesis_block["chain_id"], - state_root=genesis_block["state_root"] + conn = sqlite3.connect(str(db_path)) + cursor = conn.cursor() + + # Check if genesis block already exists + cursor.execute("SELECT * FROM block WHERE height=0 AND chain_id=?", (genesis_block["chain_id"],)) + existing = cursor.fetchone() + + if existing: + print(f"⚠️ Genesis block already exists in database") + return False + + # Create genesis block + cursor.execute( + """INSERT INTO block (height, hash, parent_hash, proposer, timestamp, tx_count, chain_id, state_root) + VALUES (?, ?, ?, ?, ?, ?, ?, ?)""", + ( + genesis_block["height"], + genesis_block["hash"], + genesis_block["parent_hash"], + genesis_block["proposer"], + genesis_block["timestamp"], + genesis_block["tx_count"], + genesis_block["chain_id"], + genesis_block.get("state_root", "0x00") ) - session.add(block) - - # Create genesis accounts - for alloc in allocations: - account = Account( - chain_id=genesis_block["chain_id"], - address=alloc["address"], - balance=alloc["balance"], - nonce=alloc["nonce"], - updated_at=datetime.utcnow() + ) + + # Create genesis accounts + for alloc in allocations: + cursor.execute( + """INSERT INTO account (chain_id, address, balance, nonce, updated_at) + VALUES (?, ?, ?, ?, ?)""", + ( + genesis_block["chain_id"], + alloc["address"], + alloc["balance"], + alloc["nonce"], + datetime.utcnow().isoformat() ) - session.add(account) + ) + + conn.commit() + print(f"✅ Genesis initialized in database: {db_path}") + return True - session.commit() - print(f"✅ Genesis initialized in database: {db_path}") - return True - - except Exception as e: + except sqlite3.Error as e: print(f"❌ Error initializing genesis in database: {e}") return False + finally: + if 'conn' in locals(): + conn.close() def register_wallet_with_service(wallet_address: str, wallet_data: Dict, service_url: str = "http://localhost:8003"): diff --git a/cli/aitbc_cli.py b/cli/aitbc_cli.py index 7e786270..ca4fe0f8 100755 --- a/cli/aitbc_cli.py +++ b/cli/aitbc_cli.py @@ -1975,6 +1975,28 @@ def legacy_main(): system_parser = subparsers.add_parser("system", help="System status and information") system_parser.add_argument("--status", action="store_true", help="Show system status") + # Genesis command with subcommands + genesis_parser = subparsers.add_parser("genesis", help="Genesis block and wallet generation") + genesis_subparsers = genesis_parser.add_subparsers(dest="genesis_action", help="Genesis actions") + + # Genesis init + genesis_init_parser = genesis_subparsers.add_parser("init", help="Initialize genesis block and wallet") + genesis_init_parser.add_argument("--chain-id", default="ait-mainnet", help="Chain ID for genesis") + genesis_init_parser.add_argument("--create-wallet", action="store_true", help="Create genesis wallet with secure random key") + genesis_init_parser.add_argument("--password", help="Wallet password (auto-generated if not provided)") + genesis_init_parser.add_argument("--proposer", help="Proposer address (defaults to genesis wallet)") + genesis_init_parser.add_argument("--force", action="store_true", help="Force overwrite existing genesis") + genesis_init_parser.add_argument("--register-service", action="store_true", help="Register genesis wallet with wallet service") + genesis_init_parser.add_argument("--service-url", default="http://localhost:8003", help="Wallet service URL") + + # Genesis verify + genesis_verify_parser = genesis_subparsers.add_parser("verify", help="Verify genesis block and wallet configuration") + genesis_verify_parser.add_argument("--chain-id", default="ait-mainnet", help="Chain ID to verify") + + # Genesis info + genesis_info_parser = genesis_subparsers.add_parser("info", help="Show genesis block information") + genesis_info_parser.add_argument("--chain-id", default="ait-mainnet", help="Chain ID to show info for") + # Blockchain command with subcommands blockchain_parser = subparsers.add_parser("blockchain", help="Blockchain operations") blockchain_subparsers = blockchain_parser.add_subparsers(dest="blockchain_action", help="Blockchain actions") @@ -2490,6 +2512,153 @@ def legacy_main(): else: print("System operation completed") + elif args.command == "genesis": + import subprocess + import sys + from pathlib import Path + + 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}") + sys.exit(1) + + if args.genesis_action == "init": + cmd = [sys.executable, str(script_path), "--chain-id", getattr(args, 'chain_id', 'ait-mainnet')] + + if hasattr(args, 'create_wallet') and args.create_wallet: + cmd.append("--create-wallet") + if hasattr(args, 'password') and args.password: + cmd.extend(["--password", args.password]) + if hasattr(args, 'proposer') and args.proposer: + cmd.extend(["--proposer", args.proposer]) + if hasattr(args, 'force') and args.force: + cmd.append("--force") + if hasattr(args, 'register_service') and args.register_service: + cmd.append("--register-service") + if hasattr(args, 'service_url') and args.service_url: + cmd.extend(["--service-url", args.service_url]) + + try: + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + print(result.stdout) + if result.stderr: + print(result.stderr) + except subprocess.CalledProcessError as e: + print(f"Error: Genesis generation failed: {e.stderr}") + sys.exit(1) + + elif args.genesis_action == "verify": + import json + import sqlite3 + + chain_id = getattr(args, 'chain_id', 'ait-mainnet') + + # Check genesis config file + genesis_path = Path(f"/var/lib/aitbc/data/{chain_id}/genesis.json") + if not genesis_path.exists(): + print(f"Error: Genesis config not found: {genesis_path}") + sys.exit(1) + + try: + with open(genesis_path) as f: + genesis_data = json.load(f) + + print(f"✓ Genesis config found: {genesis_path}") + print(f" Chain ID: {genesis_data.get('chain_id')}") + print(f" Genesis Hash: {genesis_data.get('block', {}).get('hash')}") + print(f" Proposer: {genesis_data.get('block', {}).get('proposer')}") + print(f" Allocations: {len(genesis_data.get('allocations', []))}") + except Exception as e: + print(f"Error: Failed to read genesis config: {e}") + sys.exit(1) + + # Check database + db_path = Path("/var/lib/aitbc/data/chain.db") + if not db_path.exists(): + print(f"Error: Database not found: {db_path}") + sys.exit(1) + + try: + conn = sqlite3.connect(str(db_path)) + cursor = conn.cursor() + + cursor.execute("SELECT * FROM block WHERE height=0 AND chain_id=?", (chain_id,)) + genesis_block = cursor.fetchone() + + if genesis_block: + print(f"✓ Genesis block found in database") + print(f" Height: {genesis_block[1]}") + print(f" Hash: {genesis_block[2]}") + print(f" Proposer: {genesis_block[4]}") + else: + print(f"Error: Genesis block not found in database for chain {chain_id}") + + cursor.execute("SELECT COUNT(*) FROM account WHERE chain_id=?", (chain_id,)) + account_count = cursor.fetchone()[0] + + if account_count > 0: + print(f"✓ Found {account_count} accounts in database") + else: + print(f"Error: No accounts found in database for chain {chain_id}") + + conn.close() + except Exception as e: + print(f"Error: Failed to verify database: {e}") + sys.exit(1) + + # Check genesis wallet + wallet_path = Path("/var/lib/aitbc/keystore/genesis.json") + if wallet_path.exists(): + print(f"✓ Genesis wallet found: {wallet_path}") + try: + with open(wallet_path) as f: + wallet_data = json.load(f) + print(f" Address: {wallet_data.get('address')}") + print(f" Public Key: {wallet_data.get('public_key')[:16]}..." if wallet_data.get('public_key') else "N/A") + except Exception as e: + print(f"Error: Failed to read genesis wallet: {e}") + else: + print(f"Error: Genesis wallet not found: {wallet_path}") + + elif args.genesis_action == "info": + import json + + chain_id = getattr(args, 'chain_id', 'ait-mainnet') + genesis_path = Path(f"/var/lib/aitbc/data/{chain_id}/genesis.json") + + if not genesis_path.exists(): + print(f"Error: Genesis config not found: {genesis_path}") + sys.exit(1) + + try: + with open(genesis_path) as f: + genesis_data = json.load(f) + + block = genesis_data.get("block", {}) + allocations = genesis_data.get("allocations", []) + + print(f"Genesis Information for {chain_id}:") + print(f" Chain ID: {genesis_data.get('chain_id')}") + print(f" Block Height: {block.get('height')}") + print(f" Block Hash: {block.get('hash')}") + print(f" Parent Hash: {block.get('parent_hash')}") + print(f" Proposer: {block.get('proposer')}") + print(f" Timestamp: {block.get('timestamp')}") + print(f" Transaction Count: {block.get('tx_count')}") + print(f" Total Allocations: {len(allocations)}") + print(f"\n Top Allocations:") + for i, alloc in enumerate(allocations[:5], 1): + print(f" {i}. {alloc.get('address')}: {alloc.get('balance')} AIT") + + except Exception as e: + print(f"Error: Failed to read genesis info: {e}") + sys.exit(1) + + else: + print(f"Error: Unknown genesis action: {args.genesis_action}") + sys.exit(1) + elif args.command == "blockchain": rpc_url = getattr(args, 'rpc_url', DEFAULT_RPC_URL) if args.blockchain_action == "info": @@ -2722,8 +2891,22 @@ def legacy_main(): def main(argv=None): + # Handle genesis commands directly to avoid unified_cli import issues + if argv is None: + argv = sys.argv[1:] + + if len(argv) > 0 and argv[0] == "genesis": + # Use the standalone genesis CLI + import subprocess + genesis_cli_path = Path("/opt/aitbc/cli/genesis_cli.py") + if genesis_cli_path.exists(): + result = subprocess.run([sys.executable, str(genesis_cli_path)] + argv[1:]) + return result.returncode + else: + print("Error: Genesis CLI not found at /opt/aitbc/cli/genesis_cli.py") + return 1 + from unified_cli import run_cli - return run_cli(argv, globals()) diff --git a/cli/genesis_cli.py b/cli/genesis_cli.py new file mode 100755 index 00000000..3ed98900 --- /dev/null +++ b/cli/genesis_cli.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python3 +""" +Genesis CLI - Standalone genesis block and wallet generation commands +""" + +import argparse +import subprocess +import sys +import json +import sqlite3 +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") + + if not script_path.exists(): + print(f"Error: Genesis generation script not found: {script_path}") + 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]) + + try: + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + print(result.stdout) + if result.stderr: + print(result.stderr) + return 0 + except subprocess.CalledProcessError as e: + print(f"Error: Genesis generation failed: {e.stderr}") + return 1 + + +def handle_genesis_verify(args): + """Verify genesis block and wallet configuration""" + chain_id = args.chain_id + + # Check genesis config file + genesis_path = Path(f"/var/lib/aitbc/data/{chain_id}/genesis.json") + if not genesis_path.exists(): + print(f"Error: Genesis config not found: {genesis_path}") + return 1 + + try: + with open(genesis_path) as f: + genesis_data = json.load(f) + + print(f"✓ Genesis config found: {genesis_path}") + print(f" Chain ID: {genesis_data.get('chain_id')}") + print(f" Genesis Hash: {genesis_data.get('block', {}).get('hash')}") + print(f" Proposer: {genesis_data.get('block', {}).get('proposer')}") + print(f" Allocations: {len(genesis_data.get('allocations', []))}") + except Exception as e: + print(f"Error: Failed to read genesis config: {e}") + return 1 + + # Check database + db_path = Path("/var/lib/aitbc/data/chain.db") + if not db_path.exists(): + print(f"Error: Database not found: {db_path}") + return 1 + + try: + conn = sqlite3.connect(str(db_path)) + cursor = conn.cursor() + + cursor.execute("SELECT * FROM block WHERE height=0 AND chain_id=?", (chain_id,)) + genesis_block = cursor.fetchone() + + if genesis_block: + print(f"✓ Genesis block found in database") + print(f" Height: {genesis_block[1]}") + print(f" Hash: {genesis_block[2]}") + print(f" Proposer: {genesis_block[4]}") + else: + print(f"Error: Genesis block not found in database for chain {chain_id}") + + cursor.execute("SELECT COUNT(*) FROM account WHERE chain_id=?", (chain_id,)) + account_count = cursor.fetchone()[0] + + if account_count > 0: + print(f"✓ Found {account_count} accounts in database") + else: + print(f"Error: No accounts found in database for chain {chain_id}") + + conn.close() + except Exception as e: + print(f"Error: Failed to verify database: {e}") + return 1 + + # Check genesis wallet + wallet_path = Path("/var/lib/aitbc/keystore/genesis.json") + if wallet_path.exists(): + print(f"✓ Genesis wallet found: {wallet_path}") + try: + with open(wallet_path) as f: + wallet_data = json.load(f) + print(f" Address: {wallet_data.get('address')}") + print(f" Public Key: {wallet_data.get('public_key')[:16]}..." if wallet_data.get('public_key') else "N/A") + except Exception as e: + print(f"Error: Failed to read genesis wallet: {e}") + else: + print(f"Error: Genesis wallet not found: {wallet_path}") + + return 0 + + +def handle_genesis_info(args): + """Show genesis block information""" + chain_id = args.chain_id + genesis_path = Path(f"/var/lib/aitbc/data/{chain_id}/genesis.json") + + if not genesis_path.exists(): + print(f"Error: Genesis config not found: {genesis_path}") + return 1 + + try: + with open(genesis_path) as f: + genesis_data = json.load(f) + + block = genesis_data.get("block", {}) + allocations = genesis_data.get("allocations", []) + + print(f"Genesis Information for {chain_id}:") + print(f" Chain ID: {genesis_data.get('chain_id')}") + print(f" Block Height: {block.get('height')}") + print(f" Block Hash: {block.get('hash')}") + print(f" Parent Hash: {block.get('parent_hash')}") + print(f" Proposer: {block.get('proposer')}") + print(f" Timestamp: {block.get('timestamp')}") + print(f" Transaction Count: {block.get('tx_count')}") + print(f" Total Allocations: {len(allocations)}") + print(f"\n Top Allocations:") + for i, alloc in enumerate(allocations[:5], 1): + print(f" {i}. {alloc.get('address')}: {alloc.get('balance')} AIT") + + except Exception as e: + print(f"Error: Failed to read genesis info: {e}") + return 1 + + return 0 + + +def main(): + parser = argparse.ArgumentParser( + description="AITBC Genesis CLI - Genesis block and wallet generation", + epilog="Examples: genesis-cli init --create-wallet | genesis-cli verify | genesis-cli info" + ) + + subparsers = parser.add_subparsers(dest="command", help="Genesis commands") + + # Init command + init_parser = subparsers.add_parser("init", help="Initialize genesis block and wallet") + init_parser.add_argument("--chain-id", default="ait-mainnet", help="Chain ID for genesis") + init_parser.add_argument("--create-wallet", action="store_true", help="Create genesis wallet with secure random key") + init_parser.add_argument("--password", help="Wallet password (auto-generated if not provided)") + init_parser.add_argument("--proposer", help="Proposer address (defaults to genesis wallet)") + init_parser.add_argument("--force", action="store_true", help="Force overwrite existing genesis") + init_parser.add_argument("--register-service", action="store_true", help="Register genesis wallet with wallet service") + init_parser.add_argument("--service-url", default="http://localhost:8003", help="Wallet service URL") + init_parser.set_defaults(handler=handle_genesis_init) + + # Verify command + verify_parser = subparsers.add_parser("verify", help="Verify genesis block and wallet configuration") + verify_parser.add_argument("--chain-id", default="ait-mainnet", help="Chain ID to verify") + verify_parser.set_defaults(handler=handle_genesis_verify) + + # Info command + info_parser = subparsers.add_parser("info", help="Show genesis block information") + info_parser.add_argument("--chain-id", default="ait-mainnet", help="Chain ID to show info for") + info_parser.set_defaults(handler=handle_genesis_info) + + args = parser.parse_args() + + if not args.command: + parser.print_help() + return 1 + + return args.handler(args) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/cli/unified_cli.py b/cli/unified_cli.py index 8011151f..90ecd4f0 100755 --- a/cli/unified_cli.py +++ b/cli/unified_cli.py @@ -499,12 +499,169 @@ def run_cli(argv, core): def handle_bridge_status(args): bridge_handlers.handle_bridge_status(args) - def handle_bridge_config(args): - bridge_handlers.handle_bridge_config(args) - def handle_bridge_restart(args): - bridge_handlers.handle_bridge_restart(args) + """Restart blockchain event bridge service (via systemd)""" + import subprocess + try: + result = subprocess.run(["systemctl", "restart", "aitbc-blockchain-bridge.service"], capture_output=True, text=True) + if result.returncode == 0: + print("✅ Blockchain event bridge service restarted successfully") + else: + print(f"❌ Failed to restart blockchain event bridge service: {result.stderr}") + except Exception as e: + print(f"❌ Error restarting blockchain event bridge service: {e}") +def handle_genesis_init(args): + """Initialize genesis block and wallet""" + import subprocess + import sys + from pathlib import Path + + 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}") + 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]) + + try: + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + print(result.stdout) + if result.stderr: + print(result.stderr) + except subprocess.CalledProcessError as e: + print(f"Error: Genesis generation failed: {e.stderr}") + +def handle_genesis_verify(args): + """Verify genesis block and wallet configuration""" + import json + import sqlite3 + from pathlib import Path + + chain_id = args.chain_id + + # Check genesis config file + genesis_path = Path(f"/var/lib/aitbc/data/{chain_id}/genesis.json") + if not genesis_path.exists(): + print(f"Error: Genesis config not found: {genesis_path}") + return + + try: + with open(genesis_path) as f: + genesis_data = json.load(f) + + print(f"✓ Genesis config found: {genesis_path}") + print(f" Chain ID: {genesis_data.get('chain_id')}") + print(f" Genesis Hash: {genesis_data.get('block', {}).get('hash')}") + print(f" Proposer: {genesis_data.get('block', {}).get('proposer')}") + print(f" Allocations: {len(genesis_data.get('allocations', []))}") + except Exception as e: + print(f"Error: Failed to read genesis config: {e}") + return + + # Check database + db_path = Path("/var/lib/aitbc/data/chain.db") + if not db_path.exists(): + print(f"Error: Database not found: {db_path}") + return + + try: + conn = sqlite3.connect(str(db_path)) + cursor = conn.cursor() + + cursor.execute("SELECT * FROM block WHERE height=0 AND chain_id=?", (chain_id,)) + genesis_block = cursor.fetchone() + + if genesis_block: + print(f"✓ Genesis block found in database") + print(f" Height: {genesis_block[1]}") + print(f" Hash: {genesis_block[2]}") + print(f" Proposer: {genesis_block[4]}") + else: + print(f"Error: Genesis block not found in database for chain {chain_id}") + + cursor.execute("SELECT COUNT(*) FROM account WHERE chain_id=?", (chain_id,)) + account_count = cursor.fetchone()[0] + + if account_count > 0: + print(f"✓ Found {account_count} accounts in database") + else: + print(f"Error: No accounts found in database for chain {chain_id}") + + conn.close() + except Exception as e: + print(f"Error: Failed to verify database: {e}") + return + + # Check genesis wallet + wallet_path = Path("/var/lib/aitbc/keystore/genesis.json") + if wallet_path.exists(): + print(f"✓ Genesis wallet found: {wallet_path}") + try: + with open(wallet_path) as f: + wallet_data = json.load(f) + print(f" Address: {wallet_data.get('address')}") + print(f" Public Key: {wallet_data.get('public_key')[:16]}..." if wallet_data.get('public_key') else "N/A") + except Exception as e: + print(f"Error: Failed to read genesis wallet: {e}") + else: + print(f"Error: Genesis wallet not found: {wallet_path}") + +def handle_genesis_info(args): + """Show genesis block information""" + import json + from pathlib import Path + + chain_id = args.chain_id + genesis_path = Path(f"/var/lib/aitbc/data/{chain_id}/genesis.json") + + if not genesis_path.exists(): + print(f"Error: Genesis config not found: {genesis_path}") + return + + try: + with open(genesis_path) as f: + genesis_data = json.load(f) + + block = genesis_data.get("block", {}) + allocations = genesis_data.get("allocations", []) + + print(f"Genesis Information for {chain_id}:") + print(f" Chain ID: {genesis_data.get('chain_id')}") + print(f" Block Height: {block.get('height')}") + print(f" Block Hash: {block.get('hash')}") + print(f" Parent Hash: {block.get('parent_hash')}") + print(f" Proposer: {block.get('proposer')}") + print(f" Timestamp: {block.get('timestamp')}") + print(f" Transaction Count: {block.get('tx_count')}") + print(f" Total Allocations: {len(allocations)}") + print(f"\n Top Allocations:") + for i, alloc in enumerate(allocations[:5], 1): + print(f" {i}. {alloc.get('address')}: {alloc.get('balance')} AIT") + + except Exception as e: + print(f"Error: Failed to read genesis info: {e}") + +def handle_bridge_config(args): + bridge_handlers.handle_bridge_config(args) + +def handle_bridge_restart(args): + bridge_handlers.handle_bridge_restart(args) + +def main(): parser = argparse.ArgumentParser( description="AITBC CLI - Comprehensive Blockchain Management Tool", epilog="Examples: aitbc wallet create demo secret | aitbc wallet balance demo | aitbc ai submit --wallet demo --type text-generation --prompt 'hello' --payment 1", @@ -1154,6 +1311,28 @@ def run_cli(argv, core): economics_optimize_parser.add_argument("--target", choices=["revenue", "cost", "all"], default="all") economics_optimize_parser.set_defaults(handler=handle_economics_action) + genesis_parser = subparsers.add_parser("genesis", help="Genesis block and wallet generation") + genesis_parser.set_defaults(handler=lambda parsed, parser=genesis_parser: parser.print_help()) + genesis_subparsers = genesis_parser.add_subparsers(dest="genesis_action") + + genesis_init_parser = genesis_subparsers.add_parser("init", help="Initialize genesis block and wallet") + genesis_init_parser.add_argument("--chain-id", default="ait-mainnet", help="Chain ID for genesis") + genesis_init_parser.add_argument("--create-wallet", action="store_true", help="Create genesis wallet with secure random key") + genesis_init_parser.add_argument("--password", help="Wallet password (auto-generated if not provided)") + genesis_init_parser.add_argument("--proposer", help="Proposer address (defaults to genesis wallet)") + genesis_init_parser.add_argument("--force", action="store_true", help="Force overwrite existing genesis") + genesis_init_parser.add_argument("--register-service", action="store_true", help="Register genesis wallet with wallet service") + genesis_init_parser.add_argument("--service-url", default="http://localhost:8003", help="Wallet service URL") + genesis_init_parser.set_defaults(handler=handle_genesis_init) + + genesis_verify_parser = genesis_subparsers.add_parser("verify", help="Verify genesis block and wallet configuration") + genesis_verify_parser.add_argument("--chain-id", default="ait-mainnet", help="Chain ID to verify") + genesis_verify_parser.set_defaults(handler=handle_genesis_verify) + + genesis_info_parser = genesis_subparsers.add_parser("info", help="Show genesis block information") + genesis_info_parser.add_argument("--chain-id", default="ait-mainnet", help="Chain ID to show info for") + genesis_info_parser.set_defaults(handler=handle_genesis_info) + cluster_parser = subparsers.add_parser("cluster", help="Cluster management") cluster_parser.set_defaults(handler=lambda parsed, parser=cluster_parser: parser.print_help()) cluster_subparsers = cluster_parser.add_subparsers(dest="cluster_action")