add genesis command to CLI
Some checks failed
Blockchain Synchronization Verification / sync-verification (push) Failing after 3s
CLI Tests / test-cli (push) Failing after 3s
Documentation Validation / validate-docs (push) Successful in 5s
Documentation Validation / validate-policies-strict (push) Successful in 3s
Integration Tests / test-service-integration (push) Successful in 1m10s
Multi-Node Blockchain Health Monitoring / health-check (push) Successful in 2s
P2P Network Verification / p2p-verification (push) Successful in 1s
Python Tests / test-python (push) Failing after 10s
Security Scanning / security-scan (push) Successful in 1m10s

Imported genesis command module and registered it with the CLI command group.
This commit is contained in:
aitbc
2026-04-25 18:04:54 +02:00
parent 787ddcdae3
commit ca228163ea
5 changed files with 979 additions and 0 deletions

View File

@@ -0,0 +1,111 @@
#!/usr/bin/env python3
"""Create a new genesis wallet with secure random private key"""
import json
import hashlib
from cryptography.hazmat.primitives.asymmetric import ed25519
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
from datetime import datetime
import secrets
import base64
import os
from pathlib import Path
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
def derive_address_from_public_key(pub_key_bytes: bytes) -> str:
"""Derive AITBC address from public key"""
# Hash the public key
digest = hashlib.sha256(pub_key_bytes).digest()
# Take first 20 bytes and encode as hex
address_hash = digest[:20].hex()
# Return with aitbc1 prefix
return f"aitbc1{address_hash}"
def create_genesis_wallet(password: str = None):
"""Create genesis wallet with secure random private key"""
# Generate cryptographically secure random private key (32 bytes)
private_key_bytes = secrets.token_bytes(32)
# Generate Ed25519 key pair from private key
private_key = ed25519.Ed25519PrivateKey.from_private_bytes(private_key_bytes)
public_key = private_key.public_key()
# Get public key bytes
pub_key_bytes = public_key.public_bytes(
encoding=serialization.Encoding.Raw,
format=serialization.PublicFormat.Raw
)
# Derive address
address = derive_address_from_public_key(pub_key_bytes)
# Convert to ait1 prefix format (matching genesis.json format)
ait_address = address.replace("aitbc1", "ait1")
# Generate password if not provided
if not password:
password = secrets.token_urlsafe(32)
# Encrypt private key with password
salt = secrets.token_bytes(16)
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
)
key = kdf.derive(password.encode())
# Encrypt using AES-GCM
aesgcm = AESGCM(key)
nonce = secrets.token_bytes(12)
ciphertext = aesgcm.encrypt(nonce, private_key_bytes, None)
# Create wallet data
wallet_data = {
"address": ait_address,
"public_key": pub_key_bytes.hex(),
"crypto": {
"kdf": "pbkdf2",
"kdfparams": {
"salt": salt.hex(),
"c": 100000,
"dklen": 32,
"prf": "hmac-sha256"
},
"cipher": "aes-256-gcm",
"cipherparams": {
"nonce": nonce.hex()
},
"ciphertext": ciphertext.hex()
},
"version": 1
}
# Write to keystore
keystore_path = Path("/var/lib/aitbc/keystore/genesis.json")
with open(keystore_path, 'w') as f:
json.dump(wallet_data, f, indent=2)
# Save password to secure file
password_path = Path("/var/lib/aitbc/keystore/.genesis_password")
with open(password_path, 'w') as f:
f.write(password)
os.chmod(password_path, 0o600)
print(f"✅ Created new genesis wallet with secure random private key")
print(f"Address: {ait_address}")
print(f"Public key: {pub_key_bytes.hex()}")
print(f"Private key: {private_key_bytes.hex()}")
print(f"Password: {password}")
print(f"Wallet saved to: {keystore_path}")
print(f"Password saved to: {password_path}")
print(f"⚠️ IMPORTANT: Store the password securely!")
return ait_address, pub_key_bytes.hex(), private_key_bytes.hex(), password
if __name__ == "__main__":
create_genesis_wallet()

View File

@@ -0,0 +1,350 @@
#!/usr/bin/env python3
"""
Unified Genesis Block and Wallet Generation
This script combines genesis block creation with genesis wallet generation,
connected to the wallet service for proper key management and storage.
Usage:
python3 unified_genesis.py --chain-id ait-mainnet --create-wallet
python3 unified_genesis.py --chain-id ait-mainnet --force
"""
import json
import hashlib
import argparse
import secrets
import base64
import os
import sys
from pathlib import Path
from datetime import datetime
from typing import Dict, List, Any, Optional
from cryptography.hazmat.primitives.asymmetric import ed25519
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
# Add project paths
sys.path.insert(0, '/opt/aitbc')
sys.path.insert(0, '/opt/aitbc/apps/blockchain-node/src')
try:
from aitbc_chain.config import BlockchainConfig
from aitbc_chain.models import Block, Account
from sqlmodel import Session, create_engine, select
except ImportError:
print("Warning: Could not import blockchain modules, running in wallet-only mode")
def derive_address_from_public_key(pub_key_bytes: bytes) -> str:
"""Derive AITBC address from public key"""
digest = hashlib.sha256(pub_key_bytes).digest()
address_hash = digest[:20].hex()
return f"aitbc1{address_hash}"
def compute_block_hash(height: int, parent_hash: str, timestamp: datetime, chain_id: str = "ait-mainnet") -> str:
"""Compute block hash"""
hash_input = f"{height}{parent_hash}{timestamp.isoformat()}{chain_id}".encode()
return hashlib.sha256(hash_input).hexdigest()
def create_genesis_wallet(password: str = None, chain_id: str = "ait-mainnet") -> Dict[str, str]:
"""Create genesis wallet with secure random private key"""
# Generate cryptographically secure random private key
private_key_bytes = secrets.token_bytes(32)
# Generate Ed25519 key pair
private_key = ed25519.Ed25519PrivateKey.from_private_bytes(private_key_bytes)
public_key = private_key.public_key()
# Get public key bytes
pub_key_bytes = public_key.public_bytes(
encoding=serialization.Encoding.Raw,
format=serialization.PublicFormat.Raw
)
# Derive address
address = derive_address_from_public_key(pub_key_bytes)
ait_address = address.replace("aitbc1", "ait1")
# Generate password if not provided
if not password:
password = secrets.token_urlsafe(32)
# Encrypt private key with password
salt = secrets.token_bytes(16)
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
)
key = kdf.derive(password.encode())
# Encrypt using AES-GCM
aesgcm = AESGCM(key)
nonce = secrets.token_bytes(12)
ciphertext = aesgcm.encrypt(nonce, private_key_bytes, None)
# Create wallet data
wallet_data = {
"address": ait_address,
"public_key": pub_key_bytes.hex(),
"crypto": {
"kdf": "pbkdf2",
"kdfparams": {
"salt": salt.hex(),
"c": 100000,
"dklen": 32,
"prf": "hmac-sha256"
},
"cipher": "aes-256-gcm",
"cipherparams": {
"nonce": nonce.hex()
},
"ciphertext": ciphertext.hex()
},
"version": 1
}
return {
"wallet": wallet_data,
"address": ait_address,
"public_key": pub_key_bytes.hex(),
"private_key": private_key_bytes.hex(),
"password": password
}
def create_genesis_block(chain_id: str, proposer: str, timestamp: datetime = None) -> Dict[str, Any]:
"""Create genesis block"""
if not timestamp:
timestamp = datetime.fromisoformat("2025-01-01 00:00:00")
parent_hash = "0x00"
genesis_hash = compute_block_hash(0, parent_hash, timestamp, chain_id)
genesis_block = {
"height": 0,
"hash": genesis_hash,
"parent_hash": parent_hash,
"proposer": proposer,
"timestamp": timestamp.isoformat(),
"tx_count": 0,
"chain_id": chain_id,
"state_root": "0x00",
"metadata": {
"chain_type": "mainnet",
"purpose": "production",
"consensus_algorithm": "poa"
}
}
return genesis_block
def create_genesis_allocations(genesis_address: str, additional_allocations: List[Dict] = None) -> List[Dict]:
"""Create genesis allocations including genesis wallet"""
allocations = [
{
"address": genesis_address,
"balance": 1000000000, # 1 billion AIT for genesis
"nonce": 0
}
]
if additional_allocations:
allocations.extend(additional_allocations)
return allocations
def save_genesis_wallet(wallet_data: Dict, keystore_path: Path, password: str):
"""Save genesis wallet to keystore"""
keystore_path.parent.mkdir(parents=True, exist_ok=True)
with open(keystore_path, 'w') as f:
json.dump(wallet_data, f, indent=2)
# Save password securely
password_path = keystore_path.parent / ".genesis_password"
with open(password_path, 'w') as f:
f.write(password)
os.chmod(password_path, 0o600)
def save_genesis_json(genesis_block: Dict, allocations: List[Dict], genesis_path: Path):
"""Save genesis configuration to JSON file"""
genesis_path.parent.mkdir(parents=True, exist_ok=True)
genesis_config = {
"chain_id": genesis_block["chain_id"],
"block": genesis_block,
"allocations": allocations
}
with open(genesis_path, 'w') as f:
json.dump(genesis_config, f, indent=2)
def initialize_genesis_database(genesis_block: Dict, allocations: List[Dict], db_path: Path):
"""Initialize blockchain database with genesis data"""
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"]
)
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()
)
session.add(account)
session.commit()
print(f"✅ Genesis initialized in database: {db_path}")
return True
except Exception as e:
print(f"❌ Error initializing genesis in database: {e}")
return False
def register_wallet_with_service(wallet_address: str, wallet_data: Dict, service_url: str = "http://localhost:8003"):
"""Register genesis wallet with wallet daemon service"""
try:
import httpx
response = httpx.post(
f"{service_url}/api/wallet",
json={
"address": wallet_address,
"public_key": wallet_data["public_key"],
"wallet_type": "genesis"
},
timeout=5
)
if response.status_code in (200, 201):
print(f"✅ Genesis wallet registered with wallet service")
return True
else:
print(f"⚠️ Failed to register with wallet service: {response.status_code}")
return False
except Exception as e:
print(f"⚠️ Could not connect to wallet service: {e}")
return False
def main():
parser = argparse.ArgumentParser(description="Unified Genesis Block and Wallet Generation")
parser.add_argument("--chain-id", default="ait-mainnet", help="Chain ID")
parser.add_argument("--proposer", help="Proposer address (defaults to genesis wallet)")
parser.add_argument("--create-wallet", action="store_true", help="Create genesis wallet")
parser.add_argument("--password", help="Wallet password (auto-generated if not provided)")
parser.add_argument("--db-path", default="/var/lib/aitbc/data/chain.db", help="Database path")
parser.add_argument("--keystore-path", default="/var/lib/aitbc/keystore/genesis.json", help="Keystore path")
parser.add_argument("--genesis-path", default="/var/lib/aitbc/data/ait-mainnet/genesis.json", help="Genesis config path")
parser.add_argument("--force", action="store_true", help="Force overwrite existing genesis")
parser.add_argument("--register-service", action="store_true", help="Register with wallet service")
parser.add_argument("--service-url", default="http://localhost:8003", help="Wallet service URL")
args = parser.parse_args()
print(f"🌟 Unified Genesis Generation for {args.chain_id}")
print("=" * 60)
# Create genesis wallet
if args.create_wallet:
print(f"\n📝 Creating Genesis Wallet...")
wallet_result = create_genesis_wallet(args.password, args.chain_id)
print(f"Address: {wallet_result['address']}")
print(f"Public key: {wallet_result['public_key']}")
print(f"Private key: {wallet_result['private_key']}")
print(f"Password: {wallet_result['password']}")
save_genesis_wallet(wallet_result['wallet'], Path(args.keystore_path), wallet_result['password'])
print(f"Wallet saved to: {args.keystore_path}")
proposer = args.proposer or wallet_result['address']
else:
proposer = args.proposer or "genesis"
wallet_result = None
# Create genesis block
print(f"\n📦 Creating Genesis Block...")
genesis_block = create_genesis_block(args.chain_id, proposer)
print(f"Height: {genesis_block['height']}")
print(f"Hash: {genesis_block['hash']}")
print(f"Proposer: {genesis_block['proposer']}")
# Create allocations
print(f"\n💰 Creating Genesis Allocations...")
if wallet_result:
allocations = create_genesis_allocations(wallet_result['address'])
else:
allocations = create_genesis_allocations(proposer)
print(f"Total allocations: {len(allocations)}")
for alloc in allocations[:3]: # Show first 3
print(f" - {alloc['address']}: {alloc['balance']} AIT")
# Save genesis configuration
print(f"\n💾 Saving Genesis Configuration...")
save_genesis_json(genesis_block, allocations, Path(args.genesis_path))
print(f"Genesis config saved to: {args.genesis_path}")
# Initialize database
print(f"\n🗄️ Initializing Database...")
if initialize_genesis_database(genesis_block, allocations, Path(args.db_path)):
print(f"Database initialized: {args.db_path}")
# Register with wallet service
if args.register_service and wallet_result:
print(f"\n🔗 Registering with Wallet Service...")
register_wallet_with_service(wallet_result['address'], wallet_result['wallet'], args.service_url)
print(f"\n✅ Unified Genesis Generation Complete!")
print(f"\n📋 Summary:")
print(f" Chain ID: {args.chain_id}")
print(f" Genesis Block: {genesis_block['hash']}")
if wallet_result:
print(f" Genesis Wallet: {wallet_result['address']}")
print(f" Wallet Password: {wallet_result['password']}")
print(f" ⚠️ IMPORTANT: Store the password securely!")
print(f" Database: {args.db_path}")
print(f" Config: {args.genesis_path}")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,194 @@
"""Genesis block and wallet generation commands for AITBC CLI"""
import click
from typing import Optional
from ..utils import output, error, success
import subprocess
import sys
from pathlib import Path
@click.group()
def genesis():
"""Genesis block and wallet generation commands"""
pass
@genesis.command()
@click.option("--chain-id", default="ait-mainnet", help="Chain ID for genesis")
@click.option("--create-wallet", is_flag=True, help="Create genesis wallet with secure random key")
@click.option("--password", help="Wallet password (auto-generated if not provided)")
@click.option("--proposer", help="Proposer address (defaults to genesis wallet)")
@click.option("--force", is_flag=True, help="Force overwrite existing genesis")
@click.option("--register-service", is_flag=True, help="Register genesis wallet with wallet service")
@click.option("--service-url", default="http://localhost:8003", help="Wallet service URL")
@click.pass_context
def init(ctx, chain_id: str, create_wallet: bool, password: Optional[str], proposer: Optional[str],
force: bool, register_service: bool, service_url: str):
"""Initialize genesis block and wallet for a blockchain"""
script_path = Path("/opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py")
if not script_path.exists():
error(f"Genesis generation script not found: {script_path}")
return
# Build command
cmd = [
sys.executable,
str(script_path),
"--chain-id", chain_id
]
if create_wallet:
cmd.append("--create-wallet")
if password:
cmd.extend(["--password", password])
if proposer:
cmd.extend(["--proposer", proposer])
if force:
cmd.append("--force")
if register_service:
cmd.append("--register-service")
cmd.extend(["--service-url", service_url])
try:
success(f"Running genesis generation for {chain_id}...")
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
output(result.stdout, ctx.obj.get("output_format", "table"))
success(f"Genesis generation completed successfully")
except subprocess.CalledProcessError as e:
error(f"Genesis generation failed: {e.stderr}")
return
@genesis.command()
@click.option("--chain-id", default="ait-mainnet", help="Chain ID to verify")
@click.pass_context
def verify(ctx, chain_id: str):
"""Verify genesis block and wallet configuration"""
import json
import sqlite3
# Check genesis config file
genesis_path = Path(f"/var/lib/aitbc/data/{chain_id}/genesis.json")
if not genesis_path.exists():
error(f"Genesis config not found: {genesis_path}")
return
try:
with open(genesis_path) as f:
genesis_data = json.load(f)
success(f"✓ Genesis config found: {genesis_path}")
output({
"chain_id": genesis_data.get("chain_id"),
"genesis_hash": genesis_data.get("block", {}).get("hash"),
"proposer": genesis_data.get("block", {}).get("proposer"),
"allocations_count": len(genesis_data.get("allocations", []))
}, ctx.obj.get("output_format", "table"))
except Exception as e:
error(f"Failed to read genesis config: {e}")
return
# Check database
db_path = Path("/var/lib/aitbc/data/chain.db")
if not db_path.exists():
error(f"Database not found: {db_path}")
return
try:
conn = sqlite3.connect(str(db_path))
cursor = conn.cursor()
# Check genesis block
cursor.execute("SELECT * FROM block WHERE height=0 AND chain_id=?", (chain_id,))
genesis_block = cursor.fetchone()
if genesis_block:
success(f"✓ Genesis block found in database")
output({
"height": genesis_block[1],
"hash": genesis_block[2],
"proposer": genesis_block[4]
}, ctx.obj.get("output_format", "table"))
else:
error(f"Genesis block not found in database for chain {chain_id}")
# Check genesis accounts
cursor.execute("SELECT COUNT(*) FROM account WHERE chain_id=?", (chain_id,))
account_count = cursor.fetchone()[0]
if account_count > 0:
success(f"✓ Found {account_count} accounts in database")
else:
error(f"No accounts found in database for chain {chain_id}")
conn.close()
except Exception as e:
error(f"Failed to verify database: {e}")
return
# Check genesis wallet
wallet_path = Path("/var/lib/aitbc/keystore/genesis.json")
if wallet_path.exists():
success(f"✓ Genesis wallet found: {wallet_path}")
try:
with open(wallet_path) as f:
wallet_data = json.load(f)
output({
"address": wallet_data.get("address"),
"public_key": wallet_data.get("public_key")[:16] + "..." if wallet_data.get("public_key") else None
}, ctx.obj.get("output_format", "table"))
except Exception as e:
error(f"Failed to read genesis wallet: {e}")
else:
error(f"Genesis wallet not found: {wallet_path}")
@genesis.command()
@click.option("--chain-id", default="ait-mainnet", help="Chain ID to show info for")
@click.pass_context
def info(ctx, chain_id: str):
"""Show genesis block information"""
import json
import sqlite3
genesis_path = Path(f"/var/lib/aitbc/data/{chain_id}/genesis.json")
if not genesis_path.exists():
error(f"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", [])
output({
"chain_id": genesis_data.get("chain_id"),
"genesis_block": {
"height": block.get("height"),
"hash": block.get("hash"),
"parent_hash": block.get("parent_hash"),
"proposer": block.get("proposer"),
"timestamp": block.get("timestamp"),
"tx_count": block.get("tx_count")
},
"allocations": [
{
"address": alloc.get("address"),
"balance": alloc.get("balance"),
"nonce": alloc.get("nonce")
}
for alloc in allocations[:5] # Show first 5
],
"total_allocations": len(allocations)
}, ctx.obj.get("output_format", "table"))
except Exception as e:
error(f"Failed to read genesis info: {e}")

View File

@@ -11,6 +11,7 @@ from pathlib import Path
from aitbc_cli.commands.gpu_marketplace import gpu from aitbc_cli.commands.gpu_marketplace import gpu
from aitbc_cli.commands.exchange_island import exchange_island from aitbc_cli.commands.exchange_island import exchange_island
from aitbc_cli.commands.wallet import wallet from aitbc_cli.commands.wallet import wallet
from aitbc_cli.commands.genesis import genesis
# Force version to 0.2.2 # Force version to 0.2.2
__version__ = "0.2.2" __version__ = "0.2.2"
@@ -159,6 +160,7 @@ cli.add_command(version)
cli.add_command(gpu) cli.add_command(gpu)
cli.add_command(exchange_island) cli.add_command(exchange_island)
cli.add_command(wallet) cli.add_command(wallet)
cli.add_command(genesis)
if __name__ == '__main__': if __name__ == '__main__':
cli() cli()

322
docs/genesis_generation.md Normal file
View File

@@ -0,0 +1,322 @@
# Genesis Block and Wallet Generation Guide
This guide explains how to use the unified genesis generation system for AITBC blockchain initialization.
## Overview
The unified genesis generation system combines:
- **Genesis Block Creation**: Creates the initial block for a blockchain
- **Genesis Wallet Creation**: Generates a secure genesis wallet with known private key
- **Wallet Service Integration**: Registers the genesis wallet with the wallet daemon service
- **Database Initialization**: Sets up the blockchain database with genesis data
## Prerequisites
- Python 3.13+
- AITBC blockchain node installed
- Wallet daemon service running (optional, for service integration)
- Database directory: `/var/lib/aitbc/data/`
- Keystore directory: `/var/lib/aitbc/keystore/`
## Installation
The unified genesis script is located at:
```
/opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py
```
Make it executable:
```bash
chmod +x /opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py
```
## Usage
### Basic Usage
Create genesis block and wallet for mainnet:
```bash
python3 /opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py \
--chain-id ait-mainnet \
--create-wallet
```
### Advanced Options
```bash
python3 /opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py \
--chain-id ait-mainnet \
--create-wallet \
--password "your_secure_password" \
--proposer "custom_proposer_address" \
--db-path /var/lib/aitbc/data/chain.db \
--keystore-path /var/lib/aitbc/keystore/genesis.json \
--genesis-path /var/lib/aitbc/data/ait-mainnet/genesis.json \
--force \
--register-service \
--service-url http://localhost:8003
```
### Command-Line Options
| Option | Description | Default |
|--------|-------------|---------|
| `--chain-id` | Chain ID for genesis | `ait-mainnet` |
| `--proposer` | Proposer address (defaults to genesis wallet) | `genesis` |
| `--create-wallet` | Create genesis wallet with secure random key | `False` |
| `--password` | Wallet password (auto-generated if not provided) | auto-generated |
| `--db-path` | Database file path | `/var/lib/aitbc/data/chain.db` |
| `--keystore-path` | Keystore file path | `/var/lib/aitbc/keystore/genesis.json` |
| `--genesis-path` | Genesis config file path | `/var/lib/aitbc/data/ait-mainnet/genesis.json` |
| `--force` | Force overwrite existing genesis | `False` |
| `--register-service` | Register genesis wallet with wallet service | `False` |
| `--service-url` | Wallet service URL | `http://localhost:8003` |
## Workflow
### Step 1: Create Genesis Wallet and Block
```bash
# Stop blockchain node if running
systemctl stop aitbc-blockchain-node.service
# Generate genesis
python3 /opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py \
--chain-id ait-mainnet \
--create-wallet \
--force
# Start blockchain node
systemctl start aitbc-blockchain-node.service
```
### Step 2: Verify Genesis
```bash
# Check genesis block
curl http://localhost:8006/rpc/block/0
# Check genesis wallet balance
/opt/aitbc/aitbc-cli wallet balance genesis --chain-id ait-mainnet
```
### Step 3: Register with Wallet Service (Optional)
```bash
# Ensure wallet daemon is running
systemctl status aitbc-wallet-daemon.service
# Register genesis wallet
python3 /opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py \
--chain-id ait-mainnet \
--register-service \
--service-url http://localhost:8003
```
## Security Considerations
### Private Key Security
- The script generates a cryptographically secure random private key
- Private key is encrypted with AES-256-GCM
- Password is derived using PBKDF2 with 100,000 iterations
- Password is saved to `/var/lib/aitbc/keystore/.genesis_password` with 0600 permissions
### Important Security Notes
1. **Store the password securely**: The password is saved to `.genesis_password` but should be backed up to a secure location
2. **Never share the private key**: The private key should only be known by authorized personnel
3. **Use strong passwords**: If providing a custom password, use a strong, unique password
4. **Backup the keystore**: The genesis wallet file should be backed up securely
5. **Rotate keys periodically**: For production, consider key rotation policies
## Multi-Chain Support
The script supports multiple chains:
```bash
# Mainnet
python3 /opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py \
--chain-id ait-mainnet \
--create-wallet
# Devnet
python3 /opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py \
--chain-id ait-devnet \
--create-wallet \
--db-path /var/lib/aitbc/data/ait-devnet/chain.db \
--genesis-path /var/lib/aitbc/data/ait-devnet/genesis.json
# Testnet
python3 /opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py \
--chain-id ait-testnet \
--create-wallet \
--db-path /var/lib/aitbc/data/ait-testnet/chain.db \
--genesis-path /var/lib/aitbc/data/ait-testnet/genesis.json
```
## Troubleshooting
### Database Locked Error
If you get a database locked error:
```bash
# Stop the blockchain node
systemctl stop aitbc-blockchain-node.service
# Run genesis generation
python3 /opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py \
--chain-id ait-mainnet \
--create-wallet
# Start the blockchain node
systemctl start aitbc-blockchain-node.service
```
### Genesis Already Exists
If genesis already exists in the database:
```bash
# Use --force to overwrite
python3 /opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py \
--chain-id ait-mainnet \
--create-wallet \
--force
```
### Wallet Service Connection Failed
If wallet service registration fails:
```bash
# Check if wallet daemon is running
systemctl status aitbc-wallet-daemon.service
# Start wallet daemon if not running
systemctl start aitbc-wallet-daemon.service
# Verify service URL
curl http://localhost:8003/health
```
## Integration with Wallet Service
The unified genesis script can register the genesis wallet with the wallet daemon service for enhanced wallet management capabilities:
### Benefits of Wallet Service Integration
- Centralized wallet management
- Automatic wallet synchronization
- Enhanced security features
- Transaction signing delegation
- Multi-wallet support
### Registration Process
```bash
python3 /opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py \
--chain-id ait-mainnet \
--create-wallet \
--register-service \
--service-url http://localhost:8003
```
The script will:
1. Create the genesis wallet
2. Register it with the wallet service
3. Store the wallet credentials securely
4. Enable wallet service operations
## Examples
### Example 1: Fresh Mainnet Setup
```bash
# Complete fresh setup for mainnet
systemctl stop aitbc-blockchain-node.service
python3 /opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py \
--chain-id ait-mainnet \
--create-wallet \
--force
systemctl start aitbc-blockchain-node.service
/opt/aitbc/aitbc-cli wallet balance genesis --chain-id ait-mainnet
```
### Example 2: Devnet with Custom Password
```bash
# Devnet setup with custom password
python3 /opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py \
--chain-id ait-devnet \
--create-wallet \
--password "my_secure_devnet_password" \
--db-path /var/lib/aitbc/data/ait-devnet/chain.db \
--genesis-path /var/lib/aitbc/data/ait-devnet/genesis.json
```
### Example 3: Register Existing Genesis with Service
```bash
# Register existing genesis wallet with service
python3 /opt/aitbc/apps/blockchain-node/scripts/unified_genesis.py \
--chain-id ait-mainnet \
--register-service \
--service-url http://localhost:8003
```
## Output Files
After running the script, the following files are created:
1. **Genesis Wallet**: `/var/lib/aitbc/keystore/genesis.json`
- Encrypted wallet file with genesis credentials
- Contains address, public key, encrypted private key
2. **Password File**: `/var/lib/aitbc/keystore/.genesis_password`
- Plain text password file (0600 permissions)
- Should be backed up securely
3. **Genesis Config**: `/var/lib/aitbc/data/{chain_id}/genesis.json`
- Genesis block configuration
- Account allocations
- Chain metadata
4. **Database**: `/var/lib/aitbc/data/chain.db`
- Blockchain database with genesis block
- Genesis accounts
- Chain state
## Verification
After genesis generation, verify the setup:
```bash
# Check genesis block in database
sqlite3 /var/lib/aitbc/data/chain.db "SELECT * FROM block WHERE height=0;"
# Check genesis accounts
sqlite3 /var/lib/aitbc/data/chain.db "SELECT address, balance FROM account WHERE chain_id='ait-mainnet';"
# Check wallet balance via CLI
/opt/aitbc/aitbc-cli wallet balance genesis --chain-id ait-mainnet
# Check blockchain node status
curl http://localhost:8006/health
```
## Best Practices
1. **Always backup** the genesis wallet and password before running
2. **Use --force** only when necessary, as it overwrites existing genesis
3. **Test on devnet** before applying to mainnet
4. **Document** the genesis password in a secure location
5. **Monitor** the blockchain node after genesis initialization
6. **Verify** all services are running after genesis setup
7. **Keep** the genesis script updated with the latest blockchain changes
## Support
For issues or questions:
- Check the blockchain node logs: `journalctl -u aitbc-blockchain-node.service -f`
- Check the wallet daemon logs: `journalctl -u aitbc-wallet-daemon.service -f`
- Review the script output for error messages
- Consult the AITBC documentation for additional guidance