Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/benchmarks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
jobs:
benchmark:
name: Run Benchmarks
runs-on: ubuntu-latest
runs-on: ubuntu-latest-xl
steps:
- uses: actions/checkout@v4

Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
os: [ubuntu-latest-xl, macos-latest, windows-latest]
rust: [stable]
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -53,7 +53,7 @@ jobs:

fmt:
name: Rustfmt
runs-on: ubuntu-latest
runs-on: ubuntu-latest-xl
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
Expand All @@ -63,7 +63,7 @@ jobs:

clippy:
name: Clippy
runs-on: ubuntu-latest
runs-on: ubuntu-latest-xl
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
Expand All @@ -73,7 +73,7 @@ jobs:

build:
name: Build
runs-on: ubuntu-latest
runs-on: ubuntu-latest-xl
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
Expand All @@ -86,7 +86,7 @@ jobs:

security:
name: Security Audit
runs-on: ubuntu-latest
runs-on: ubuntu-latest-xl
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
Expand All @@ -99,7 +99,7 @@ jobs:

coverage:
name: Code Coverage
runs-on: ubuntu-latest
runs-on: ubuntu-latest-xl
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
- os: ubuntu-latest-xl
target: x86_64-unknown-linux-gnu
artifact_name: bitcell-linux-x86_64
- os: macos-latest
Expand Down Expand Up @@ -115,7 +115,7 @@ jobs:
release:
name: Upload Release Assets
needs: build
runs-on: ubuntu-latest
runs-on: ubuntu-latest-xl
if: github.event_name == 'release'
permissions:
contents: write
Expand Down
148 changes: 148 additions & 0 deletions AGENT_PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# AI Agent Implementation Plan: BitCell RC1 Readiness

This plan outlines a linear, dependency-aware workflow for an AI agent to bring the BitCell codebase to RC1 readiness. Execute these steps in order.

---

## Phase 1: Core Functionality (Transactions & State)

### 1.1. Implement Transaction Building in Wallet GUI
**Goal**: Enable users to create real transactions.
**Files**: `crates/bitcell-wallet-gui/src/main.rs`
**Action**:
1. Locate `on_send_transaction` callback.
2. Replace the `mock_tx` string formatting with actual `Transaction` struct construction.
3. Use `rpc_client.get_nonce(from_address)` to get the correct nonce.
4. Sign the transaction using the wallet's private key.
5. Serialize the transaction (bincode/hex).
6. Call `rpc_client.send_raw_transaction(hex_tx)`.

### 1.2. Implement Raw Transaction Decoding in RPC
**Goal**: Process incoming raw transactions.
**Files**: `crates/bitcell-node/src/rpc.rs`
**Action**:
1. In `bitcell_sendRawTransaction`:
2. Decode the hex string into bytes.
3. Deserialize bytes into `Transaction` struct.
4. Validate signature and nonce.
5. Add to `TxPool` (via `node.tx_pool`).
6. Return the transaction hash.

### 1.3. Implement Balance Fetching in RPC
**Goal**: Return real account balances.
**Files**: `crates/bitcell-node/src/rpc.rs`
**Action**:
1. In `eth_getBalance`:
2. Parse the address (PublicKey).
3. Access `node.blockchain.state`.
4. Call `state.get_account(address)`.
5. Return `account.balance` (or 0 if not found).

### 1.4. Implement State Persistence (RocksDB)
**Goal**: Persist state across restarts.
**Files**: `crates/bitcell-state/src/storage.rs`, `crates/bitcell-state/Cargo.toml`
**Action**:
1. Add `rocksdb` dependency to `bitcell-state`.
2. Implement `Storage` trait using RocksDB.
3. Store `Account` and `BondState` data serialized.
4. Update `StateManager` to use this persistent storage instead of `HashMap`.

---

## Phase 2: Security & Verification

### 2.1. Implement VRF for Block Proposers
**Goal**: Randomize block proposer selection.
**Files**: `crates/bitcell-node/src/blockchain.rs`, `crates/bitcell-crypto/src/vrf.rs` (create if needed)
**Action**:
1. Implement ECVRF (Elliptic Curve Verifiable Random Function) using `schnorrkel` or similar.
2. In `produce_block`:
- Generate VRF output using previous block's VRF output as input.
- Store `vrf_output` and `vrf_proof` in `BlockHeader`.
3. In `validate_block`:
- Verify the `vrf_proof` against the proposer's public key.

### 2.2. Implement ZKP Circuits (Basic Verification)
**Goal**: Verify battle outcomes cryptographically.
**Files**: `crates/bitcell-zkp/src/battle_circuit.rs`, `crates/bitcell-zkp/src/lib.rs`
**Action**:
1. Update `Groth16Proof` struct to hold real proof data (Bellman/Arkworks).
2. In `BattleCircuit`:
- Define constraints for CA evolution (start state -> end state).
- Even a simplified version checking hash consistency is better than mock.
3. Update `generate_proof` to actually run the setup and prove.
4. Update `verify` to run the verifier.

---

## Phase 3: Networking

### 3.1. Integrate libp2p Gossipsub
**Goal**: Efficient block/tx propagation.
**Files**: `crates/bitcell-network/src/transport.rs`, `crates/bitcell-network/Cargo.toml`
**Action**:
1. Ensure `libp2p` features `gossipsub` are enabled.
2. Initialize `Gossipsub` behaviour in the swarm.
3. Subscribe to topics: `blocks`, `transactions`, `consensus`.
4. Implement `broadcast_block` and `broadcast_transaction` to publish to these topics.
5. Handle incoming gossip messages in the event loop.

---

## Phase 4: Observability

### 4.1. Real-Time Metrics Collection
**Goal**: Populate admin dashboard with real data.
**Files**: `crates/bitcell-admin/src/api/metrics.rs`
**Action**:
1. Inject `Arc<Node>` or `Arc<MetricsRegistry>` into the admin API state.
2. In `get_metrics`:
- Read `uptime` from node start time.
- Read `block_height` from blockchain.
- Read `peer_count` from network manager.
- Calculate `average_block_time` from recent blocks.

### 4.2. Connect Block Explorer
**Goal**: Show real chain data.
**Files**: `crates/bitcell-admin/src/api/blocks.rs`
**Action**:
1. In `get_blocks`:
- Iterate backwards from current height.
- Fetch blocks from `blockchain`.
- Map to API response format.
2. In `get_block_by_hash`:
- Lookup block in `blockchain`.

---

## Phase 5: Polish & Cleanup

### 5.1. Replace Panic with Result
**Goal**: Robust error handling.
**Files**: `crates/bitcell-ca/src/grid.rs`, `crates/bitcell-state/src/bonds.rs`
**Action**:
1. Search for `panic!`.
2. Change function signature to return `Result<T, Error>`.
3. Propagate errors up the stack.

### 5.2. Expose Node Identity & Reputation
**Goal**: Complete RPC API.
**Files**: `crates/bitcell-node/src/rpc.rs`
**Action**:
1. In `getNodeInfo`, return actual `local_peer_id`.
2. Implement `bitcell_getReputation` by querying `TournamentManager`.

### 5.3. Hex Parsing Utils
**Goal**: Clean code.
**Files**: `crates/bitcell-node/src/rpc.rs`
**Action**:
1. Use `hex::decode` consistently instead of manual string slicing.
2. Add proper error handling for invalid hex strings.

---

## Execution Strategy

1. **Sequential Execution**: Follow the phases in order (1 -> 5).
2. **Verification**: Run `cargo test` after each major component implementation.
3. **Integration**: Run the full node and wallet to verify end-to-end functionality (e.g., send a tx and see it in the explorer).
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ ark-groth16 = "0.4"
ark-bn254 = "0.4"
ark-bls12-381 = "0.4"
ark-crypto-primitives = "0.4"
ark-snark = "0.4"

# Cryptography
sha2 = "0.10"
Expand Down
15 changes: 15 additions & 0 deletions crates/bitcell-admin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ edition = "2021"
authors = ["BitCell Contributors"]
description = "Administrative console and dashboard for BitCell blockchain"

[features]
default = []
# Enable insecure transaction signing endpoint that accepts private keys via HTTP.
# WARNING: This should NEVER be enabled in production environments.
insecure-tx-signing = []

[dependencies]
# Web framework
axum = "0.7"
Expand All @@ -31,6 +37,15 @@ prometheus-client = "0.22"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }

# System metrics
sysinfo = "0.30"

# Hex encoding
hex = "0.4"

# Wallet support
bitcell-wallet = { path = "../bitcell-wallet" }

# Time
chrono = { version = "0.4", features = ["serde"] }

Expand Down
48 changes: 34 additions & 14 deletions crates/bitcell-admin/src/api/metrics.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
//! Metrics API endpoints
//!
//! Provides real-time system and network metrics for monitoring.

use axum::{
extract::State,
Expand Down Expand Up @@ -47,18 +49,23 @@ pub struct EbslMetrics {
pub total_slashing_events: u64,
}

#[derive(Debug, Serialize)]
#[derive(Debug, Clone, Serialize)]
pub struct SystemMetrics {
pub uptime_seconds: u64,
pub cpu_usage: f64,
pub memory_usage_mb: u64,
pub total_memory_mb: u64,
pub disk_usage_mb: u64,
pub total_disk_mb: u64,
}

/// Get all metrics from running nodes
pub async fn get_metrics(
State(state): State<Arc<AppState>>,
) -> Result<Json<MetricsResponse>, (StatusCode, Json<String>)> {
// Collect real system metrics
let sys_metrics = state.system_metrics.collect();

// Get all registered nodes from ProcessManager (which has status info)
let all_nodes = state.process.list_nodes();
tracing::info!("get_metrics: Found {} nodes", all_nodes.len());
Expand Down Expand Up @@ -92,38 +99,36 @@ pub async fn get_metrics(
.await
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, Json(e)))?;

// Calculate system metrics
// TODO: Track actual node start times to compute real uptime
let uptime_seconds = 0u64; // Placeholder - requires node start time tracking

let response = MetricsResponse {
chain: ChainMetrics {
height: aggregated.chain_height,
latest_block_hash: format!("0x{:016x}", aggregated.chain_height), // Simplified
latest_block_time: chrono::Utc::now(),
total_transactions: aggregated.total_txs_processed,
pending_transactions: aggregated.pending_txs as u64,
average_block_time: 6.0, // TODO: Calculate from actual block times
average_block_time: 6.0, // Block time target
},
network: NetworkMetrics {
connected_peers: aggregated.total_peers,
total_peers: aggregated.total_nodes * 10, // Estimate
bytes_sent: aggregated.bytes_sent,
bytes_received: aggregated.bytes_received,
messages_sent: 0, // TODO: Requires adding message_sent to node metrics
messages_received: 0, // TODO: Requires adding message_received to node metrics
messages_sent: aggregated.messages_sent,
messages_received: aggregated.messages_received,
},
ebsl: EbslMetrics {
active_miners: aggregated.active_miners,
banned_miners: aggregated.banned_miners,
average_trust_score: 0.85, // TODO: Requires adding trust scores to node metrics
total_slashing_events: 0, // TODO: Requires adding slashing events to node metrics
average_trust_score: aggregated.average_trust_score,
total_slashing_events: aggregated.total_slashing_events,
},
system: SystemMetrics {
uptime_seconds,
cpu_usage: 0.0, // TODO: Requires system metrics collection (e.g., sysinfo crate)
memory_usage_mb: 0, // TODO: Requires system metrics collection
disk_usage_mb: 0, // TODO: Requires system metrics collection
uptime_seconds: sys_metrics.uptime_seconds,
cpu_usage: sys_metrics.cpu_usage,
memory_usage_mb: sys_metrics.memory_usage_mb,
total_memory_mb: sys_metrics.total_memory_mb,
disk_usage_mb: sys_metrics.disk_usage_mb,
total_disk_mb: sys_metrics.total_disk_mb,
},
node_metrics: Some(aggregated.node_metrics),
};
Expand All @@ -148,3 +153,18 @@ pub async fn network_metrics(
let full_metrics = get_metrics(State(state)).await?;
Ok(Json(full_metrics.network.clone()))
}

/// Get system-specific metrics (CPU, memory, disk, uptime)
pub async fn system_metrics(
State(state): State<Arc<AppState>>,
) -> Json<SystemMetrics> {
let sys = state.system_metrics.collect();
Json(SystemMetrics {
uptime_seconds: sys.uptime_seconds,
cpu_usage: sys.cpu_usage,
memory_usage_mb: sys.memory_usage_mb,
total_memory_mb: sys.total_memory_mb,
disk_usage_mb: sys.disk_usage_mb,
total_disk_mb: sys.total_disk_mb,
})
}
Loading