feat(node): wire nu-p2p via HTTP publish API

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Mukan Erkin TÖRÜK 2026-04-24 16:49:37 +03:00
parent c22c0e0278
commit ec8af8d1c7
5 changed files with 919 additions and 24 deletions

View file

@ -7,6 +7,16 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
## [Unreleased]
## [0.8.0] — 2026-04-24
### Added
- `--p2p-api <url>` CLI flag — nu-p2p publish API adresi; verildiğinde P2P forwarding loop aktif olur
- `reqwest` HTTP client ile nu-p2p `/publish` endpoint'ine `BlockAnnounce` ve `TxGossip` mesajları iletilir
- `nu-node``nu-p2p` entegrasyonu tamamlandı: block loop ürettiği her blok için announce, RPC üzerinden kabul edilen her tx için gossip gönderir
### Changed
- `--p2p-addr` / `--bootstrap` flag'leri kaldırıldı; yerini `--p2p-api` aldı (process sınırı korunuyor, nu-p2p ayrı process olarak çalışıyor)
## [0.7.0] — 2026-04-24
### Added

View file

@ -46,6 +46,15 @@ cargo fmt && cargo clippy
## Faz Durumu
- **Faz 0 (şu an):** Scaffold tamam. Modül sınırları tanımlı, tipler yazıldı.
- **Faz 1:** Tx execution (TokenTransfer önce), tek validator devnet, JSON-RPC server.
- **Faz 2:** PoN consensus tam implementasyon, slashing, 3+ validator.
- **Faz 0:** ✅ Scaffold, tipler, modül sınırları.
- **Faz 1:** ✅ Tüm tx tipleri, block loop, JSON-RPC, P2P forwarding (`--p2p-api`).
- **Faz 2 (sıradaki):** Tam PoN consensus (rotation, slashing), 3+ validator testnet.
## P2P Entegrasyonu
nu-node, nu-p2p'ye `reqwest` ile HTTP POST atar. nu-p2p ayrı process olarak çalışır.
```bash
# P2P ile başlat
cargo run -- --dev --validator --p2p-api http://127.0.0.1:30334
```

879
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -46,6 +46,7 @@ sha2.workspace = true
hex.workspace = true
chrono.workspace = true
serde_json.workspace = true
reqwest = { version = "0.12", features = ["json"] }
nu-consensus = { path = "crates/nu-consensus" }
nu-mempool = { path = "crates/nu-mempool" }
nu-state = { path = "crates/nu-state" }

View file

@ -42,13 +42,10 @@ struct Cli {
#[arg(long, default_value = "nu-devnet-1")]
chain_id: String,
/// P2P listen address (empty = P2P disabled)
/// nu-p2p publish API address (empty = P2P disabled)
/// e.g. http://127.0.0.1:30334
#[arg(long)]
p2p_addr: Option<String>,
/// Bootstrap peer multiaddrs
#[arg(long)]
bootstrap: Vec<String>,
p2p_api: Option<String>,
}
#[tokio::main]
@ -64,28 +61,43 @@ async fn main() -> Result<()> {
tracing::info!("State DB opened at {}", cli.db_path);
// P2P event channel — block_loop and RPC publish, forwarded to nu-p2p swarm
let (p2p_sender, rpc_p2p_tx) = if cli.p2p_addr.is_some() {
// P2P event channel — block_loop and RPC publish, forwarded to nu-p2p via HTTP
let (p2p_sender, rpc_p2p_tx) = if let Some(ref api_url) = cli.p2p_api {
let (block_tx, mut block_rx) = mpsc::channel::<NodeP2pEvent>(128);
let (rpc_tx, mut rpc_rx) = rpc_mpsc::channel::<Vec<u8>>(256);
let publish_url = format!("{}/publish", api_url.trim_end_matches('/'));
let client = reqwest::Client::new();
tokio::spawn(async move {
loop {
tokio::select! {
Some(event) = block_rx.recv() => {
match &event {
let body = match &event {
NodeP2pEvent::BlockAnnounce { height, hash } => {
tracing::info!(height, hash = %&hash[..8], "p2p: block announce");
serde_json::json!({
"type": "BlockAnnounce",
"data": { "height": height, "hash": hash }
})
}
NodeP2pEvent::TxGossip { raw_tx } => {
tracing::debug!(bytes = raw_tx.len(), "p2p: tx gossip");
serde_json::json!({
"type": "TxGossip",
"data": { "raw_tx": raw_tx }
})
}
}
// TODO: forward to nu-p2p swarm
};
let _ = client.post(&publish_url).json(&body).send().await;
}
Some(raw) = rpc_rx.recv() => {
tracing::debug!(bytes = raw.len(), "p2p: rpc tx gossip");
// TODO: forward to nu-p2p swarm
let body = serde_json::json!({
"type": "TxGossip",
"data": { "raw_tx": raw }
});
let _ = client.post(&publish_url).json(&body).send().await;
}
else => break,
}
@ -124,7 +136,7 @@ async fn main() -> Result<()> {
rpc_addr = %cli.rpc_addr,
dev = cli.dev,
validator = cli.validator,
p2p = cli.p2p_addr.as_deref().unwrap_or("disabled"),
p2p = cli.p2p_api.as_deref().unwrap_or("disabled"),
"nu-node ready"
);