Some checks failed
AITBC CI/CD Pipeline / lint-and-test (3.11) (pull_request) Has been cancelled
AITBC CI/CD Pipeline / lint-and-test (3.12) (pull_request) Has been cancelled
AITBC CI/CD Pipeline / lint-and-test (3.13) (pull_request) Has been cancelled
Security Scanning / Bandit Security Scan (apps/coordinator-api/src) (pull_request) Has been cancelled
Security Scanning / Bandit Security Scan (cli/aitbc_cli) (pull_request) Has been cancelled
Security Scanning / Bandit Security Scan (packages/py/aitbc-core/src) (pull_request) Has been cancelled
Security Scanning / Bandit Security Scan (packages/py/aitbc-crypto/src) (pull_request) Has been cancelled
Security Scanning / Bandit Security Scan (packages/py/aitbc-sdk/src) (pull_request) Has been cancelled
Security Scanning / Bandit Security Scan (tests) (pull_request) Has been cancelled
Security Scanning / CodeQL Security Analysis (javascript) (pull_request) Has been cancelled
Security Scanning / CodeQL Security Analysis (python) (pull_request) Has been cancelled
Security Scanning / Dependency Security Scan (pull_request) Has been cancelled
Security Scanning / Container Security Scan (pull_request) Has been cancelled
Security Scanning / OSSF Scorecard (pull_request) Has been cancelled
AITBC CI/CD Pipeline / test-cli (pull_request) Has been cancelled
AITBC CI/CD Pipeline / test-services (pull_request) Has been cancelled
AITBC CI/CD Pipeline / test-production-services (pull_request) Has been cancelled
AITBC CI/CD Pipeline / security-scan (pull_request) Has been cancelled
AITBC CI/CD Pipeline / build (pull_request) Has been cancelled
AITBC CI/CD Pipeline / deploy-staging (pull_request) Has been cancelled
AITBC CI/CD Pipeline / deploy-production (pull_request) Has been cancelled
AITBC CI/CD Pipeline / performance-test (pull_request) Has been cancelled
AITBC CI/CD Pipeline / docs (pull_request) Has been cancelled
AITBC CI/CD Pipeline / release (pull_request) Has been cancelled
AITBC CI/CD Pipeline / notify (pull_request) Has been cancelled
Security Scanning / Security Summary Report (pull_request) Has been cancelled
- Add production genesis initialization scripts - Add keystore management for production - Add production node runner - Add setup production automation - Add AI memory system for development tracking - Add translation cache service - Add development heartbeat monitoring - Update blockchain RPC router - Update coordinator API main configuration - Update secure pickle service - Update claim task script - Update blockchain service configuration - Update gitignore for production files
158 lines
5.3 KiB
Python
158 lines
5.3 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Initialize the production chain (ait-mainnet) with genesis allocations.
|
|
This script:
|
|
- Ensures the blockchain database is initialized
|
|
- Creates the genesis block (if missing)
|
|
- Populates account balances according to the production allocation
|
|
- Outputs the addresses and their balances
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
import sys
|
|
import yaml
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
# Add the blockchain node src to path
|
|
sys.path.insert(0, str(Path(__file__).parent.parent / "apps/blockchain-node/src"))
|
|
|
|
from aitbc_chain.config import settings as cfg
|
|
from aitbc_chain.database import init_db, session_scope
|
|
from aitbc_chain.models import Block, Account
|
|
from aitbc_chain.consensus.poa import PoAProposer, ProposerConfig
|
|
from aitbc_chain.mempool import init_mempool
|
|
import hashlib
|
|
from sqlmodel import select
|
|
|
|
# Production allocations (loaded from genesis_prod.yaml if available, else fallback)
|
|
ALLOCATIONS = {}
|
|
|
|
|
|
def load_allocations() -> dict[str, int]:
|
|
yaml_path = Path("/opt/aitbc/genesis_prod.yaml")
|
|
if yaml_path.exists():
|
|
import yaml
|
|
with yaml_path.open() as f:
|
|
data = yaml.safe_load(f)
|
|
allocations = {}
|
|
for acc in data.get("genesis", {}).get("accounts", []):
|
|
addr = acc["address"]
|
|
balance = int(acc["balance"])
|
|
allocations[addr] = balance
|
|
return allocations
|
|
else:
|
|
# Fallback hardcoded
|
|
return {
|
|
"aitbc1genesis": 10_000_000,
|
|
"aitbc1treasury": 5_000_000,
|
|
"aitbc1aiengine": 2_000_000,
|
|
"aitbc1surveillance": 1_500_000,
|
|
"aitbc1analytics": 1_000_000,
|
|
"aitbc1marketplace": 2_000_000,
|
|
"aitbc1enterprise": 3_000_000,
|
|
"aitbc1multimodal": 1_500_000,
|
|
"aitbc1zkproofs": 1_000_000,
|
|
"aitbc1crosschain": 2_000_000,
|
|
"aitbc1developer1": 500_000,
|
|
"aitbc1developer2": 300_000,
|
|
"aitbc1tester": 200_000,
|
|
}
|
|
|
|
ALLOCATIONS = load_allocations()
|
|
|
|
# Authorities (proposers) for PoA
|
|
AUTHORITIES = ["aitbc1genesis"]
|
|
|
|
|
|
def compute_genesis_hash(chain_id: str, timestamp: datetime) -> str:
|
|
payload = f"{chain_id}|0|0x00|{timestamp.isoformat()}".encode()
|
|
return "0x" + hashlib.sha256(payload).hexdigest()
|
|
|
|
|
|
def ensure_genesis_block(chain_id: str) -> Block:
|
|
with session_scope() as session:
|
|
# Check if any block exists for this chain
|
|
head = session.exec(select(Block).where(Block.chain_id == chain_id).order_by(Block.height.desc()).limit(1)).first()
|
|
if head is not None:
|
|
print(f"[*] Chain already has block at height {head.height}")
|
|
return head
|
|
|
|
# Create deterministic genesis timestamp
|
|
timestamp = datetime(2025, 1, 1, 0, 0, 0)
|
|
block_hash = compute_genesis_hash(chain_id, timestamp)
|
|
genesis = Block(
|
|
chain_id=chain_id,
|
|
height=0,
|
|
hash=block_hash,
|
|
parent_hash="0x00",
|
|
proposer="genesis",
|
|
timestamp=timestamp,
|
|
tx_count=0,
|
|
state_root=None,
|
|
)
|
|
session.add(genesis)
|
|
session.commit()
|
|
print(f"[+] Created genesis block: height=0, hash={block_hash}")
|
|
return genesis
|
|
|
|
|
|
def seed_accounts(chain_id: str) -> None:
|
|
with session_scope() as session:
|
|
for address, balance in ALLOCATIONS.items():
|
|
account = session.get(Account, (chain_id, address))
|
|
if account is None:
|
|
account = Account(chain_id=chain_id, address=address, balance=balance, nonce=0)
|
|
session.add(account)
|
|
print(f"[+] Created account {address} with balance {balance}")
|
|
else:
|
|
# Already exists; ensure balance matches if we want to enforce
|
|
if account.balance != balance:
|
|
account.balance = balance
|
|
print(f"[~] Updated account {address} balance to {balance}")
|
|
session.commit()
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--chain-id", default="ait-mainnet", help="Chain ID to initialize")
|
|
parser.add_argument("--db-path", type=Path, help="Path to SQLite database (overrides config)")
|
|
args = parser.parse_args()
|
|
|
|
# Override environment for config
|
|
os.environ["CHAIN_ID"] = args.chain_id
|
|
if args.db_path:
|
|
os.environ["DB_PATH"] = str(args.db_path)
|
|
|
|
from aitbc_chain.config import Settings
|
|
settings = Settings()
|
|
|
|
print(f"[*] Initializing database at {settings.db_path}")
|
|
init_db()
|
|
print("[*] Database initialized")
|
|
|
|
# Ensure mempool DB exists (though not needed for genesis)
|
|
mempool_path = settings.db_path.parent / "mempool.db"
|
|
init_mempool(backend="database", db_path=str(mempool_path), max_size=10000, min_fee=0)
|
|
print(f"[*] Mempool initialized at {mempool_path}")
|
|
|
|
# Create genesis block
|
|
ensure_genesis_block(args.chain_id)
|
|
|
|
# Seed accounts
|
|
seed_accounts(args.chain_id)
|
|
|
|
print("\n[+] Production genesis initialization complete.")
|
|
print(f"[!] Next steps:")
|
|
print(f" 1) Generate keystore for aitbc1genesis and aitbc1treasury using scripts/keystore.py")
|
|
print(f" 2) Update .env with CHAIN_ID={args.chain_id} and PROPOSER_KEY=<private key of aitbc1genesis>")
|
|
print(f" 3) Restart the blockchain node.")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|