feat(node): wire nu-p2p via HTTP publish API
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c22c0e0278
commit
ec8af8d1c7
5 changed files with 919 additions and 24 deletions
10
CHANGELOG.md
10
CHANGELOG.md
|
|
@ -7,6 +7,16 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
||||||
|
|
||||||
## [Unreleased]
|
## [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
|
## [0.7.0] — 2026-04-24
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
||||||
15
CLAUDE.md
15
CLAUDE.md
|
|
@ -46,6 +46,15 @@ cargo fmt && cargo clippy
|
||||||
|
|
||||||
## Faz Durumu
|
## Faz Durumu
|
||||||
|
|
||||||
- **Faz 0 (şu an):** Scaffold tamam. Modül sınırları tanımlı, tipler yazıldı.
|
- **Faz 0:** ✅ Scaffold, tipler, modül sınırları.
|
||||||
- **Faz 1:** Tx execution (TokenTransfer önce), tek validator devnet, JSON-RPC server.
|
- **Faz 1:** ✅ Tüm tx tipleri, block loop, JSON-RPC, P2P forwarding (`--p2p-api`).
|
||||||
- **Faz 2:** PoN consensus tam implementasyon, slashing, 3+ validator.
|
- **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
879
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -46,6 +46,7 @@ sha2.workspace = true
|
||||||
hex.workspace = true
|
hex.workspace = true
|
||||||
chrono.workspace = true
|
chrono.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
|
reqwest = { version = "0.12", features = ["json"] }
|
||||||
nu-consensus = { path = "crates/nu-consensus" }
|
nu-consensus = { path = "crates/nu-consensus" }
|
||||||
nu-mempool = { path = "crates/nu-mempool" }
|
nu-mempool = { path = "crates/nu-mempool" }
|
||||||
nu-state = { path = "crates/nu-state" }
|
nu-state = { path = "crates/nu-state" }
|
||||||
|
|
|
||||||
38
src/main.rs
38
src/main.rs
|
|
@ -42,13 +42,10 @@ struct Cli {
|
||||||
#[arg(long, default_value = "nu-devnet-1")]
|
#[arg(long, default_value = "nu-devnet-1")]
|
||||||
chain_id: String,
|
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)]
|
#[arg(long)]
|
||||||
p2p_addr: Option<String>,
|
p2p_api: Option<String>,
|
||||||
|
|
||||||
/// Bootstrap peer multiaddrs
|
|
||||||
#[arg(long)]
|
|
||||||
bootstrap: Vec<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
|
@ -64,28 +61,43 @@ async fn main() -> Result<()> {
|
||||||
|
|
||||||
tracing::info!("State DB opened at {}", cli.db_path);
|
tracing::info!("State DB opened at {}", cli.db_path);
|
||||||
|
|
||||||
// P2P event channel — block_loop and RPC publish, forwarded to nu-p2p swarm
|
// P2P event channel — block_loop and RPC publish, forwarded to nu-p2p via HTTP
|
||||||
let (p2p_sender, rpc_p2p_tx) = if cli.p2p_addr.is_some() {
|
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 (block_tx, mut block_rx) = mpsc::channel::<NodeP2pEvent>(128);
|
||||||
let (rpc_tx, mut rpc_rx) = rpc_mpsc::channel::<Vec<u8>>(256);
|
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 {
|
tokio::spawn(async move {
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
Some(event) = block_rx.recv() => {
|
Some(event) = block_rx.recv() => {
|
||||||
match &event {
|
let body = match &event {
|
||||||
NodeP2pEvent::BlockAnnounce { height, hash } => {
|
NodeP2pEvent::BlockAnnounce { height, hash } => {
|
||||||
tracing::info!(height, hash = %&hash[..8], "p2p: block announce");
|
tracing::info!(height, hash = %&hash[..8], "p2p: block announce");
|
||||||
|
serde_json::json!({
|
||||||
|
"type": "BlockAnnounce",
|
||||||
|
"data": { "height": height, "hash": hash }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
NodeP2pEvent::TxGossip { raw_tx } => {
|
NodeP2pEvent::TxGossip { raw_tx } => {
|
||||||
tracing::debug!(bytes = raw_tx.len(), "p2p: tx gossip");
|
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() => {
|
Some(raw) = rpc_rx.recv() => {
|
||||||
tracing::debug!(bytes = raw.len(), "p2p: rpc tx gossip");
|
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,
|
else => break,
|
||||||
}
|
}
|
||||||
|
|
@ -124,7 +136,7 @@ async fn main() -> Result<()> {
|
||||||
rpc_addr = %cli.rpc_addr,
|
rpc_addr = %cli.rpc_addr,
|
||||||
dev = cli.dev,
|
dev = cli.dev,
|
||||||
validator = cli.validator,
|
validator = cli.validator,
|
||||||
p2p = cli.p2p_addr.as_deref().unwrap_or("disabled"),
|
p2p = cli.p2p_api.as_deref().unwrap_or("disabled"),
|
||||||
"nu-node ready"
|
"nu-node ready"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue