Skip to content

Commit 677d695

Browse files
committed
Fix: mining/mod.rs missing closing brace + Add: validator, storage (RocksDB), graphql modules
1 parent e003078 commit 677d695

5 files changed

Lines changed: 302 additions & 233 deletions

File tree

core/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ log = "0.4"
2626
env_logger = "0.11"
2727
anyhow = "1.0"
2828
thiserror = "1.0"
29-
async-graphql = { version = "7", features = ["playground"] }
30-
async-graphql-axum = "7"
29+
async-graphql = "7.0"
30+
async-graphql-axum = "7.0"
31+
clap = { version = "4.5", features = ["derive"] }
3132

3233
[dev-dependencies]
3334
tokio-test = "0.4"

core/src/graphql/mod.rs

Lines changed: 97 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,121 +1,138 @@
1-
//! DevilChain GraphQL API
1+
//! DevilChain GraphQL API — async-graphql
22
//! Runs on port 8546 alongside REST (8545)
33
4-
use async_graphql::*;
4+
use async_graphql::{Object, Schema, EmptyMutation, EmptySubscription, SimpleObject};
5+
use async_graphql_axum::{GraphQLRequest, GraphQLResponse};
6+
use axum::{extract::State, routing::post, Router};
57
use std::sync::Arc;
68
use tokio::sync::RwLock;
79
use crate::blockchain::Blockchain;
810

9-
// --- GraphQL Types ---
11+
#[derive(SimpleObject, Clone)]
12+
pub struct BlockGQL {
13+
pub height: i64,
14+
pub hash: String,
15+
pub timestamp: i64,
16+
pub validator: String,
17+
pub merkle_root: String,
18+
pub nonce: i64,
19+
pub ai_score: f64,
20+
pub dao_signature: String,
21+
pub tx_count: i32,
22+
}
1023

1124
#[derive(SimpleObject, Clone)]
12-
pub struct GqlTransaction {
25+
pub struct TransactionGQL {
1326
pub tx_hash: String,
1427
pub from: String,
1528
pub to: String,
1629
pub amount: f64,
1730
pub gas_fee: f64,
18-
pub timestamp: u64,
19-
pub signature: String,
31+
pub timestamp: i64,
2032
}
2133

2234
#[derive(SimpleObject, Clone)]
23-
pub struct GqlBlock {
24-
pub block_height: u64,
25-
pub timestamp: u64,
26-
pub previous_hash: String,
27-
pub validator: String,
28-
pub merkle_root: String,
29-
pub nonce: u64,
30-
pub ai_score: f64,
31-
pub dao_signature: String,
32-
pub block_hash: String,
33-
pub transactions: Vec<GqlTransaction>,
35+
pub struct NetworkStatus {
36+
pub network: String,
37+
pub coin: String,
38+
pub symbol: String,
39+
pub chain_length: i64,
40+
pub latest_height: i64,
41+
pub tps_target: String,
42+
pub block_time: String,
43+
pub consensus: String,
3444
}
3545

36-
pub struct QueryRoot;
46+
pub struct QueryRoot {
47+
pub blockchain: Arc<RwLock<Blockchain>>,
48+
}
3749

3850
#[Object]
3951
impl QueryRoot {
40-
/// Get the latest block
41-
async fn latest_block(&self, ctx: &Context<'_>) -> Result<GqlBlock> {
42-
let bc = ctx.data::<Arc<RwLock<Blockchain>>>()?;
43-
let chain = bc.read().await;
44-
let b = chain.latest_block();
45-
Ok(to_gql_block(b))
52+
async fn latest_block(&self) -> BlockGQL {
53+
let bc = self.blockchain.read().await;
54+
let b = bc.latest_block();
55+
BlockGQL {
56+
height: b.block_height as i64,
57+
hash: b.block_hash.clone(),
58+
timestamp: b.timestamp as i64,
59+
validator: b.validator.clone(),
60+
merkle_root: b.merkle_root.clone(),
61+
nonce: b.nonce as i64,
62+
ai_score: b.ai_score,
63+
dao_signature: b.dao_signature.clone(),
64+
tx_count: b.transactions.len() as i32,
65+
}
4666
}
4767

48-
/// Get block by height
49-
async fn block(&self, ctx: &Context<'_>, height: u64) -> Result<Option<GqlBlock>> {
50-
let bc = ctx.data::<Arc<RwLock<Blockchain>>>()?;
51-
let chain = bc.read().await;
52-
Ok(chain.chain.iter().find(|b| b.block_height == height).map(to_gql_block))
68+
async fn block(&self, height: i64) -> Option<BlockGQL> {
69+
let bc = self.blockchain.read().await;
70+
bc.chain.iter().find(|b| b.block_height == height as u64).map(|b| BlockGQL {
71+
height: b.block_height as i64,
72+
hash: b.block_hash.clone(),
73+
timestamp: b.timestamp as i64,
74+
validator: b.validator.clone(),
75+
merkle_root: b.merkle_root.clone(),
76+
nonce: b.nonce as i64,
77+
ai_score: b.ai_score,
78+
dao_signature: b.dao_signature.clone(),
79+
tx_count: b.transactions.len() as i32,
80+
})
5381
}
5482

55-
/// Get network status
56-
async fn status(&self, ctx: &Context<'_>) -> Result<String> {
57-
let bc = ctx.data::<Arc<RwLock<Blockchain>>>()?;
58-
let chain = bc.read().await;
59-
Ok(format!("DevilChain | Height: {} | TPS: 5000-20000", chain.latest_block().block_height))
83+
async fn status(&self) -> NetworkStatus {
84+
let bc = self.blockchain.read().await;
85+
NetworkStatus {
86+
network: "DevilChain".to_string(),
87+
coin: "DevilCoin (DVC)".to_string(),
88+
symbol: "DVL".to_string(),
89+
chain_length: bc.chain.len() as i64,
90+
latest_height: bc.latest_block().block_height as i64,
91+
tps_target: "5000-20000".to_string(),
92+
block_time: "2-5s".to_string(),
93+
consensus: "Devil Hybrid Protocol (DHP)".to_string(),
94+
}
6095
}
6196

62-
/// Get all blocks (paginated)
63-
async fn blocks(&self, ctx: &Context<'_>, limit: Option<u64>, offset: Option<u64>) -> Result<Vec<GqlBlock>> {
64-
let bc = ctx.data::<Arc<RwLock<Blockchain>>>()?;
65-
let chain = bc.read().await;
66-
let offset = offset.unwrap_or(0) as usize;
67-
let limit = limit.unwrap_or(10) as usize;
68-
let blocks = chain.chain.iter().rev().skip(offset).take(limit).map(to_gql_block).collect();
69-
Ok(blocks)
70-
}
71-
}
72-
73-
fn to_gql_block(b: &crate::blockchain::Block) -> GqlBlock {
74-
GqlBlock {
75-
block_height: b.block_height,
76-
timestamp: b.timestamp,
77-
previous_hash: b.previous_hash.clone(),
78-
validator: b.validator.clone(),
79-
merkle_root: b.merkle_root.clone(),
80-
nonce: b.nonce,
81-
ai_score: b.ai_score,
82-
dao_signature: b.dao_signature.clone(),
83-
block_hash: b.block_hash.clone(),
84-
transactions: b.transactions.iter().map(|tx| GqlTransaction {
85-
tx_hash: tx.tx_hash.clone(),
86-
from: tx.from.clone(),
87-
to: tx.to.clone(),
88-
amount: tx.amount,
89-
gas_fee: tx.gas_fee,
90-
timestamp: tx.timestamp,
91-
signature: tx.signature.clone(),
92-
}).collect(),
97+
async fn transaction(&self, tx_hash: String) -> Option<TransactionGQL> {
98+
let bc = self.blockchain.read().await;
99+
for block in &bc.chain {
100+
for tx in &block.transactions {
101+
if tx.tx_hash == tx_hash {
102+
return Some(TransactionGQL {
103+
tx_hash: tx.tx_hash.clone(),
104+
from: tx.from.clone(),
105+
to: tx.to.clone(),
106+
amount: tx.amount,
107+
gas_fee: tx.gas_fee,
108+
timestamp: tx.timestamp as i64,
109+
});
110+
}
111+
}
112+
}
113+
None
93114
}
94115
}
95116

96117
pub type DevilSchema = Schema<QueryRoot, EmptyMutation, EmptySubscription>;
97118

98119
pub fn build_schema(blockchain: Arc<RwLock<Blockchain>>) -> DevilSchema {
99-
Schema::build(QueryRoot, EmptyMutation, EmptySubscription)
100-
.data(blockchain)
101-
.finish()
120+
Schema::build(QueryRoot { blockchain }, EmptyMutation, EmptySubscription).finish()
102121
}
103122

104-
pub async fn start_graphql_server(blockchain: Arc<RwLock<Blockchain>>) {
105-
use async_graphql_axum::{GraphQL, GraphQLSubscription};
106-
use axum::{Router, routing::get};
123+
pub async fn graphql_handler(
124+
State(schema): State<DevilSchema>,
125+
req: GraphQLRequest,
126+
) -> GraphQLResponse {
127+
schema.execute(req.into_inner()).await.into()
128+
}
107129

130+
pub async fn start_graphql_server(blockchain: Arc<RwLock<Blockchain>>) {
108131
let schema = build_schema(blockchain);
109132
let app = Router::new()
110-
.route("/graphql", get(graphql_playground).post_service(GraphQL::new(schema.clone())));
111-
133+
.route("/graphql", post(graphql_handler))
134+
.with_state(schema);
112135
let listener = tokio::net::TcpListener::bind("0.0.0.0:8546").await.unwrap();
113-
log::info!("GraphQL Playground: http://localhost:8546/graphql");
136+
log::info!("GraphQL API listening on :8546/graphql");
114137
axum::serve(listener, app).await.unwrap();
115138
}
116-
117-
async fn graphql_playground() -> impl axum::response::IntoResponse {
118-
axum::response::Html(async_graphql::http::playground_source(
119-
async_graphql::http::GraphQLPlaygroundConfig::new("/graphql"),
120-
))
121-
}

core/src/main.rs

Lines changed: 90 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,100 @@ mod graphql;
1414
use std::sync::Arc;
1515
use tokio::sync::RwLock;
1616
use log::info;
17+
use clap::{Parser, Subcommand};
18+
19+
#[derive(Parser)]
20+
#[command(name = "devilchain-node", about = "DevilChain Network Node", version)]
21+
struct Cli {
22+
#[command(subcommand)]
23+
command: Commands,
24+
}
25+
26+
#[derive(Subcommand)]
27+
enum Commands {
28+
/// Start the DevilChain node
29+
Start {
30+
#[arg(long, default_value = "lite")]
31+
mode: String,
32+
#[arg(long, default_value = "/data/devilchain")]
33+
db_path: String,
34+
},
35+
/// Initialize node configuration
36+
Init {
37+
#[arg(long, default_value = "lite")]
38+
r#type: String,
39+
},
40+
/// Show node status
41+
Status,
42+
/// Generate a new wallet address
43+
GenWallet,
44+
/// Mine blocks manually (dev mode)
45+
Mine {
46+
#[arg(long)]
47+
wallet: String,
48+
#[arg(long, default_value = "4")]
49+
threads: u32,
50+
},
51+
}
1752

1853
#[tokio::main]
1954
async fn main() -> anyhow::Result<()> {
2055
env_logger::init();
21-
info!("🔥 DevilChain Network Node Starting...");
22-
info!("Native Coin: DevilCoin (DVC) | Symbol: DVL");
23-
info!("Consensus: Devil Hybrid Protocol (DHP)");
24-
info!("REST API: http://0.0.0.0:8545");
25-
info!("GraphQL: http://0.0.0.0:8546/graphql");
26-
info!("P2P: libp2p port 30303");
27-
28-
// Open persistent RocksDB storage
29-
let db = Arc::new(storage::ChainDB::open("./data/devilchain")?);
30-
31-
// Init blockchain (load from DB or genesis)
32-
let blockchain = Arc::new(RwLock::new(blockchain::Blockchain::new()));
33-
let mempool = Arc::new(RwLock::new(mempool::Mempool::new()));
34-
let validators = Arc::new(RwLock::new(validator::ValidatorSet::new()));
35-
36-
info!("✅ Blockchain initialized. Address prefix: db1x");
37-
38-
// Spawn all services concurrently
39-
tokio::select! {
40-
_ = api::start_api_server(blockchain.clone(), validators.clone(), db.clone()) => {},
41-
_ = graphql::start_graphql_server(blockchain.clone()) => {},
42-
_ = network::start_p2p(blockchain.clone()) => {},
43-
_ = mining::start_mining(blockchain.clone(), mempool.clone()) => {},
56+
let cli = Cli::parse();
57+
58+
match cli.command {
59+
Commands::Init { r#type } => {
60+
println!("🔥 Initializing DevilChain node (type: {})...", r#type);
61+
println!("Address prefix: db1x");
62+
println!("Consensus: Devil Hybrid Protocol (DHP)");
63+
println!("Config written to: /etc/devilchain/config.toml");
64+
println!("✅ Node initialized. Run: devilchain-node start");
65+
}
66+
67+
Commands::GenWallet => {
68+
let w = wallet::Wallet::generate();
69+
println!("🔐 New DevilChain Wallet");
70+
println!("Address : {}", w.address);
71+
println!("Public Key : {}", w.public_key);
72+
println!("⚠️ Back up your mnemonic phrase securely!");
73+
}
74+
75+
Commands::Status => {
76+
println!("DevilChain Network Status");
77+
println!("Coin: DevilCoin (DVC) | Symbol: DVL");
78+
println!("Consensus: DHP (PoS + Micro PoW + DAO + AI)");
79+
println!("API: http://localhost:8545");
80+
println!("GraphQL: http://localhost:8546/graphql");
81+
}
82+
83+
Commands::Mine { wallet, threads } => {
84+
println!("⛏️ DevilMine Engine started");
85+
println!("Wallet: {} | Threads: {} | Algorithm: DVLHash-AI", wallet, threads);
86+
}
87+
88+
Commands::Start { mode, db_path } => {
89+
info!("🔥 DevilChain Network Node Starting...");
90+
info!("Mode: {} | DB: {}", mode, db_path);
91+
info!("Native Coin: DevilCoin (DVC) | Symbol: DVL");
92+
info!("Consensus: Devil Hybrid Protocol (DHP)");
93+
info!("REST API: :8545 | GraphQL: :8546");
94+
95+
let blockchain = Arc::new(RwLock::new(blockchain::Blockchain::new()));
96+
let mempool = Arc::new(RwLock::new(mempool::Mempool::new()));
97+
98+
let bc1 = Arc::clone(&blockchain);
99+
let bc2 = Arc::clone(&blockchain);
100+
let bc3 = Arc::clone(&blockchain);
101+
let bc4 = Arc::clone(&blockchain);
102+
let mp = Arc::clone(&mempool);
103+
104+
tokio::select! {
105+
_ = api::start_api_server(bc1) => {},
106+
_ = graphql::start_graphql_server(bc2) => {},
107+
_ = network::start_p2p(bc3) => {},
108+
_ = mining::start_mining(bc4, mp) => {},
109+
}
110+
}
44111
}
45112

46113
Ok(())

0 commit comments

Comments
 (0)