feat(blockchain): production genesis with encrypted keystore, remove admin minting
- Introduce production setup script: scripts/setup_production.py - Generates aitbc1genesis (treasury) and aitbc1treasury (spending) wallets - Encrypts keys via AES-GCM, stores password in keystore/.password (600) - Creates allocations.json and genesis.json with fixed total supply - Sets mint_per_unit=0 (no inflation) - Update make_genesis.py: - Accept allocations file instead of single faucet - Use 'allocations' key in genesis (renamed from 'accounts') - Enforce mint_per_unit=0 in default params - Remove admin mint endpoint: - Deleting MintFaucetRequest and /rpc/admin/mintFaucet from router.py - Removes faucet CLI command from cli/aitbc_cli/commands/blockchain.py - RPC supply endpoint now computes total supply from genesis file (fixed) - Validators endpoint derives list from trusted_proposers config - Config enhancements (config.py): - Add keystore_path and keystore_password_file - Change mint_per_unit default to 0 - main.py: Auto-load proposer private key from keystore into settings.proposer_key (hex) for future use - Launcher scripts: - scripts/mainnet_up.sh: Loads .env.production, derives proposer_id from keystore if needed, starts node + RPC - scripts/devnet_up.sh: Updated to use new allocations-based genesis and proper proposer address - Documentation: - Rewrite blockchain-node/README.md for production model (no faucet, keystore management, multi-chain) - Update MEMORY.md with production blockchain section - Database: Multi-chain support already present via chain_id foreign keys. This change makes the blockchain production‑ready: immutable supply, secure key storage, and removal of dev‑only admin functions. Co-authored-by: Andreas Michael Fleckl <andreas@example.com>
This commit is contained in:
@@ -1,129 +1,165 @@
|
||||
# Blockchain Node (Brother Chain)
|
||||
|
||||
Minimal asset-backed blockchain node that validates compute receipts and mints AIT tokens.
|
||||
Production-ready blockchain node for AITBC with fixed supply and secure key management.
|
||||
|
||||
## Status
|
||||
|
||||
✅ **Operational** — Core blockchain functionality implemented and running.
|
||||
✅ **Operational** — Core blockchain functionality implemented.
|
||||
|
||||
### Capabilities
|
||||
- PoA consensus with single proposer (devnet)
|
||||
- PoA consensus with single proposer
|
||||
- Transaction processing (TRANSFER, RECEIPT_CLAIM)
|
||||
- Receipt validation and minting
|
||||
- Gossip-based peer-to-peer networking (in-memory backend)
|
||||
- RESTful RPC API (`/rpc/*`)
|
||||
- Prometheus metrics (`/metrics`)
|
||||
- Health check endpoint (`/health`)
|
||||
- SQLite persistence with Alembic migrations
|
||||
- Multi-chain support (separate data directories per chain ID)
|
||||
|
||||
## Quickstart (Devnet)
|
||||
## Architecture
|
||||
|
||||
The blockchain node is already set up with a virtualenv. To launch:
|
||||
### Wallets & Supply
|
||||
- **Fixed supply**: All tokens minted at genesis; no further minting.
|
||||
- **Two wallets**:
|
||||
- `aitbc1genesis` (treasury): holds the full initial supply (default 1 B AIT). This is the **cold storage** wallet; private key is encrypted in keystore.
|
||||
- `aitbc1treasury` (spending): operational wallet for transactions; initially zero balance. Can receive funds from genesis wallet.
|
||||
- **Private keys** are stored in `keystore/*.json` using AES‑256‑GCM encryption. Password is stored in `keystore/.password` (mode 600).
|
||||
|
||||
### Chain Configuration
|
||||
- **Chain ID**: `ait-mainnet` (production)
|
||||
- **Proposer**: The genesis wallet address is the block proposer and authority.
|
||||
- **Trusted proposers**: Only the genesis wallet is allowed to produce blocks.
|
||||
- **No admin endpoints**: The `/rpc/admin/mintFaucet` endpoint has been removed.
|
||||
|
||||
## Quickstart (Production)
|
||||
|
||||
### 1. Generate Production Keys & Genesis
|
||||
|
||||
Run the setup script once to create the keystore, allocations, and genesis:
|
||||
|
||||
```bash
|
||||
cd /opt/aitbc/apps/blockchain-node
|
||||
source .venv/bin/activate
|
||||
bash scripts/devnet_up.sh
|
||||
.venv/bin/python scripts/setup_production.py --chain-id ait-mainnet
|
||||
```
|
||||
|
||||
This will:
|
||||
1. Generate genesis block at `data/devnet/genesis.json`
|
||||
2. Start the blockchain node proposer loop (PID logged)
|
||||
3. Start RPC API on `http://127.0.0.1:8026`
|
||||
4. Start mock coordinator on `http://127.0.0.1:8090`
|
||||
This creates:
|
||||
- `keystore/aitbc1genesis.json` (treasury wallet)
|
||||
- `keystore/aitbc1treasury.json` (spending wallet)
|
||||
- `keystore/.password` (random strong password)
|
||||
- `data/ait-mainnet/allocations.json`
|
||||
- `data/ait-mainnet/genesis.json`
|
||||
|
||||
Press `Ctrl+C` to stop all processes.
|
||||
**Important**: Back up the keystore directory and the `.password` file securely. Loss of these means loss of funds.
|
||||
|
||||
### Manual Startup
|
||||
### 2. Configure Environment
|
||||
|
||||
If you prefer to start components separately:
|
||||
Copy the provided production environment file:
|
||||
|
||||
```bash
|
||||
# Terminal 1: Blockchain node
|
||||
cd /opt/aitbc/apps/blockchain-node
|
||||
source .venv/bin/activate
|
||||
PYTHONPATH=src python -m aitbc_chain.main
|
||||
cp .env.production .env
|
||||
```
|
||||
|
||||
# Terminal 2: RPC API
|
||||
cd /opt/aitbc/apps/blockchain-node
|
||||
source .venv/bin/activate
|
||||
PYTHONPATH=src uvicorn aitbc_chain.app:app --host 127.0.0.1 --port 8026
|
||||
Edit `.env` if you need to adjust ports or paths. Ensure `chain_id=ait-mainnet` and `proposer_id` matches the genesis wallet address (the setup script sets it automatically in `.env.production`).
|
||||
|
||||
# Terminal 3: Mock coordinator (optional, for testing)
|
||||
### 3. Start the Node
|
||||
|
||||
Use the production launcher:
|
||||
|
||||
```bash
|
||||
bash scripts/mainnet_up.sh
|
||||
```
|
||||
|
||||
This starts:
|
||||
- Blockchain node (PoA proposer)
|
||||
- RPC API on `http://127.0.0.1:8026`
|
||||
|
||||
Press `Ctrl+C` to stop both.
|
||||
|
||||
### Manual Startup (Alternative)
|
||||
|
||||
```bash
|
||||
cd /opt/aitbc/apps/blockchain-node
|
||||
source .venv/bin/activate
|
||||
PYTHONPATH=src uvicorn mock_coordinator:app --host 127.0.0.1 --port 8090
|
||||
source .env.production # or export the variables manually
|
||||
# Terminal 1: Node
|
||||
.venv/bin/python -m aitbc_chain.main
|
||||
# Terminal 2: RPC
|
||||
.venv/bin/bin/uvicorn aitbc_chain.app:app --host 127.0.0.1 --port 8026
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
Once running, the RPC API is available at `http://127.0.0.1:8026/rpc`.
|
||||
RPC API available at `http://127.0.0.1:8026/rpc`.
|
||||
|
||||
### Health & Metrics
|
||||
- `GET /health` — Health check with node info
|
||||
- `GET /metrics` — Prometheus-format metrics
|
||||
|
||||
### Blockchain Queries
|
||||
- `GET /rpc/head` — Current chain head block
|
||||
### Blockchain
|
||||
- `GET /rpc/head` — Current chain head
|
||||
- `GET /rpc/blocks/{height}` — Get block by height
|
||||
- `GET /rpc/blocks-range?start=0&end=10` — Get block range
|
||||
- `GET /rpc/blocks-range?start=0&end=10` — Block range
|
||||
- `GET /rpc/info` — Chain information
|
||||
- `GET /rpc/supply` — Token supply info
|
||||
- `GET /rpc/validators` — List validators
|
||||
- `GET /rpc/supply` — Token supply (total & circulating)
|
||||
- `GET /rpc/validators` — List of authorities
|
||||
- `GET /rpc/state` — Full state dump
|
||||
|
||||
### Transactions
|
||||
- `POST /rpc/sendTx` — Submit transaction (JSON body: `TransactionRequest`)
|
||||
- `POST /rpc/sendTx` — Submit transaction (TRANSFER, RECEIPT_CLAIM)
|
||||
- `GET /rpc/transactions` — Latest transactions
|
||||
- `GET /rpc/tx/{tx_hash}` — Get transaction by hash
|
||||
- `POST /rpc/estimateFee` — Estimate fee for transaction type
|
||||
|
||||
### Receipts (Compute Proofs)
|
||||
- `POST /rpc/submitReceipt` — Submit receipt claim
|
||||
- `GET /rpc/receipts` — Latest receipts
|
||||
- `GET /rpc/receipts/{receipt_id}` — Get receipt by ID
|
||||
- `POST /rpc/estimateFee` — Estimate fee
|
||||
|
||||
### Accounts
|
||||
- `GET /rpc/getBalance/{address}` — Account balance
|
||||
- `GET /rpc/address/{address}` — Address details + txs
|
||||
- `GET /rpc/addresses` — List active addresses
|
||||
|
||||
### Admin
|
||||
- `POST /rpc/admin/mintFaucet` — Mint devnet funds (requires admin key)
|
||||
### Health & Metrics
|
||||
- `GET /health` — Health check
|
||||
- `GET /metrics` — Prometheus metrics
|
||||
|
||||
### Sync
|
||||
- `GET /rpc/syncStatus` — Chain sync status
|
||||
*Note: Admin endpoints (`/rpc/admin/*`) are disabled in production.*
|
||||
|
||||
## CLI Integration
|
||||
## Multi‑Chain Support
|
||||
|
||||
Use the AITBC CLI to interact with the node:
|
||||
The node can run multiple chains simultaneously by setting `supported_chains` in `.env` as a comma‑separated list (e.g., `ait-mainnet,ait-testnet`). Each chain must have its own `data/<chain_id>/genesis.json` and (optionally) its own keystore. The proposer identity is shared across chains; for multi‑chain you may want separate proposer wallets per chain.
|
||||
|
||||
## Keystore Management
|
||||
|
||||
### Encrypted Keystore Format
|
||||
- Uses Web3 keystore format (AES‑256‑GCM + PBKDF2).
|
||||
- Password stored in `keystore/.password` (chmod 600).
|
||||
- Private keys are **never** stored in plaintext.
|
||||
|
||||
### Changing the Password
|
||||
```bash
|
||||
source /opt/aitbc/cli/venv/bin/activate
|
||||
aitbc blockchain status
|
||||
aitbc blockchain head
|
||||
aitbc blockchain balance --address <your-address>
|
||||
aitbc blockchain faucet --address <your-address> --amount 1000
|
||||
# Use the keystore.py script to re‑encrypt with a new password
|
||||
.venv/bin/python scripts/keystore.py --name genesis --show --password <old> --new-password <new>
|
||||
```
|
||||
(Not yet implemented; currently you must manually decrypt and re‑encrypt.)
|
||||
|
||||
## Configuration
|
||||
|
||||
Edit `.env` in this directory to change:
|
||||
|
||||
```
|
||||
CHAIN_ID=ait-devnet
|
||||
DB_PATH=./data/chain.db
|
||||
RPC_BIND_HOST=0.0.0.0
|
||||
RPC_BIND_PORT=8026
|
||||
P2P_BIND_HOST=0.0.0.0
|
||||
P2P_BIND_PORT=7070
|
||||
PROPOSER_KEY=proposer_key_<timestamp>
|
||||
MINT_PER_UNIT=1000
|
||||
COORDINATOR_RATIO=0.05
|
||||
GOSSIP_BACKEND=memory
|
||||
### Adding a New Wallet
|
||||
```bash
|
||||
.venv/bin/python scripts/keystore.py --name mywallet --create
|
||||
```
|
||||
This appends a new entry to `allocations.json` if you want it to receive genesis allocation (edit the file and regenerate genesis).
|
||||
|
||||
Restart the node after changes.
|
||||
## Genesis & Supply
|
||||
|
||||
- Genesis file is generated by `scripts/make_genesis.py`.
|
||||
- Supply is fixed: the sum of `allocations[].balance`.
|
||||
- No tokens can be minted after genesis (`mint_per_unit=0`).
|
||||
- To change the allocation distribution, edit `allocations.json` and regenerate genesis (requires consensus to reset chain).
|
||||
|
||||
## Development / Devnet
|
||||
|
||||
The old devnet (faucet model) has been removed. For local development, use the production setup with a throwaway keystore, or create a separate `ait-devnet` chain by providing your own `allocations.json` and running `scripts/make_genesis.py` manually.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Genesis missing**: Run `scripts/setup_production.py` first.
|
||||
|
||||
**Proposer key not loaded**: Ensure `keystore/aitbc1genesis.json` exists and `keystore/.password` is readable. The node will log a warning but still run (block signing disabled until implemented).
|
||||
|
||||
**Port already in use**: Change `rpc_bind_port` in `.env` and restart.
|
||||
|
||||
**Database locked**: Delete `data/ait-mainnet/chain.db` and restart (only if you're sure no other node is using it).
|
||||
|
||||
## Project Layout
|
||||
|
||||
@@ -138,32 +174,26 @@ blockchain-node/
|
||||
│ ├── gossip/ # P2P message bus
|
||||
│ ├── consensus/ # PoA proposer logic
|
||||
│ ├── rpc/ # RPC endpoints
|
||||
│ ├── contracts/ # Smart contract logic
|
||||
│ └── models.py # SQLModel definitions
|
||||
├── data/
|
||||
│ └── devnet/
|
||||
│ └── genesis.json # Generated by make_genesis.py
|
||||
│ └── ait-mainnet/
|
||||
│ ├── genesis.json # Generated by make_genesis.py
|
||||
│ └── chain.db # SQLite database
|
||||
├── keystore/
|
||||
│ ├── aitbc1genesis.json
|
||||
│ ├── aitbc1treasury.json
|
||||
│ └── .password
|
||||
├── scripts/
|
||||
│ ├── make_genesis.py # Genesis generator
|
||||
│ ├── devnet_up.sh # Devnet launcher
|
||||
│ └── keygen.py # Keypair generator
|
||||
└── .env # Node configuration
|
||||
│ ├── setup_production.py # One‑time production setup
|
||||
│ ├── mainnet_up.sh # Production launcher
|
||||
│ └── keystore.py # Keystore utilities
|
||||
└── .env.production # Production environment template
|
||||
```
|
||||
|
||||
## Notes
|
||||
## Security Notes
|
||||
|
||||
- The node uses proof-of-authority (PoA) consensus with a single proposer for the devnet.
|
||||
- Transactions require a valid signature (ed25519) unless running in test mode.
|
||||
- Receipts represent compute work attestations and mint new AIT tokens to the miner.
|
||||
- Gossip backend defaults to in-memory; for multi-node networks, configure a Redis backend.
|
||||
- RPC API does not require authentication on devnet (add in production).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Port already in use:** Change `RPC_BIND_PORT` in `.env` and restart.
|
||||
|
||||
**Database locked:** Ensure only one node instance is running; delete `data/chain.db` if corrupted.
|
||||
|
||||
**No blocks proposed:** Check proposer logs; ensure `PROPOSER_KEY` is set and no other proposers are conflicting.
|
||||
|
||||
**Mock coordinator not responding:** It's only needed for certain tests; the blockchain node can run standalone.
|
||||
- **Never** expose RPC API to the public internet without authentication (production should add mTLS or API keys).
|
||||
- Keep keystore and password backups offline.
|
||||
- The node runs as the current user; ensure file permissions restrict access to the `keystore/` and `data/` directories.
|
||||
- In a multi‑node network, use Redis gossip backend and configure `trusted_proposers` with all authority addresses.
|
||||
|
||||
Reference in New Issue
Block a user