Skip to content

Commit 23fae63

Browse files
VictorLuxclaude
andcommitted
fix: Resolve 29 Rust 1.93.0 Clippy lints in zipherx-network
- Add type aliases for complex callback types (MempoolTxCallback, etc.) - Group listener callbacks into ListenerCallbacks struct (too-many-args) - Replace manual div_ceil, abs_diff, is_multiple_of patterns - Use RangeInclusive::contains instead of manual range checks - Replace map_or(false, ...) with is_some_and(...) - Remove redundant closures and unnecessary borrows - Use &mut [T] instead of &mut Vec<T> in function signatures - Derive Default for PeerScore instead of manual impl - Fix doc list item indentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 87df440 commit 23fae63

6 files changed

Lines changed: 77 additions & 69 deletions

File tree

crates/zipherx-network/src/block_fetcher.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ use crate::constants::MAX_BLOCKS_PER_REQUEST;
1212
use crate::messages::{self, BlockHeader};
1313
use crate::types::NetworkError;
1414

15+
/// Parsed transaction result: (bytes_consumed, txid, outputs, spends).
16+
type ParsedTransaction = (usize, [u8; 32], Vec<ShieldedOutput>, Vec<ShieldedSpend>);
17+
1518
// ============================================================================
1619
// Types
1720
// ============================================================================
@@ -190,7 +193,7 @@ pub fn parse_raw_block(
190193
/// - binding_sig (64) — only if shielded data present
191194
pub fn parse_transaction(
192195
data: &[u8],
193-
) -> Option<(usize, [u8; 32], Vec<ShieldedOutput>, Vec<ShieldedSpend>)> {
196+
) -> Option<ParsedTransaction> {
194197
if data.len() < 12 {
195198
return None;
196199
}
@@ -371,7 +374,7 @@ pub fn parse_transaction(
371374
fn compute_txid(tx_data: &[u8]) -> [u8; 32] {
372375
use sha2::{Digest, Sha256};
373376
let first_pass = Sha256::digest(tx_data);
374-
let second_pass = Sha256::digest(&first_pass);
377+
let second_pass = Sha256::digest(first_pass);
375378
let mut txid = [0u8; 32];
376379
txid.copy_from_slice(&second_pass);
377380
txid
@@ -381,15 +384,15 @@ fn compute_txid(tx_data: &[u8]) -> [u8; 32] {
381384
pub fn compute_block_hash(header: &BlockHeader) -> [u8; 32] {
382385
use sha2::{Digest, Sha256};
383386
let base = header.serialize();
384-
let first = Sha256::digest(&base);
385-
let second = Sha256::digest(&first);
387+
let first = Sha256::digest(base);
388+
let second = Sha256::digest(first);
386389
let mut hash = [0u8; 32];
387390
hash.copy_from_slice(&second);
388391
hash
389392
}
390393

391394
/// Sort blocks by height (FIX #1199).
392-
pub fn sort_blocks_by_height(blocks: &mut Vec<CompactBlock>) {
395+
pub fn sort_blocks_by_height(blocks: &mut [CompactBlock]) {
393396
blocks.sort_by_key(|b| b.height);
394397
}
395398

@@ -400,7 +403,7 @@ pub fn calculate_rounds(start: u64, end: u64, peer_count: usize) -> usize {
400403
}
401404
let total_blocks = (end - start + 1) as usize;
402405
let blocks_per_round = peer_count * MAX_BLOCKS_PER_REQUEST;
403-
(total_blocks + blocks_per_round - 1) / blocks_per_round
406+
total_blocks.div_ceil(blocks_per_round)
404407
}
405408

406409
/// Check if a fetch result meets the 50% threshold (FIX #1218).

crates/zipherx-network/src/dispatcher.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ use std::collections::{HashMap, VecDeque};
1212

1313
use tokio::sync::oneshot;
1414

15+
use crate::types::MessagePayload;
16+
1517
/// A batch collector that accumulates multiple messages of the same type.
1618
struct BatchCollector {
1719
#[allow(dead_code)]
@@ -27,7 +29,7 @@ struct BatchCollector {
2729
/// synchronous (no awaits while holding the lock).
2830
pub struct Dispatcher {
2931
/// Single-message handlers keyed by command name, FIFO queue per command.
30-
pending: HashMap<String, VecDeque<oneshot::Sender<(String, Vec<u8>)>>>,
32+
pending: HashMap<String, VecDeque<oneshot::Sender<MessagePayload>>>,
3133

3234
/// Batch collectors keyed by monotonic ID.
3335
batch_collectors: HashMap<u64, BatchCollector>,
@@ -36,7 +38,7 @@ pub struct Dispatcher {
3638
command_to_batch: HashMap<String, Vec<u64>>,
3739

3840
/// Broadcast handlers keyed by "broadcast_{txid}".
39-
broadcast_handlers: HashMap<String, oneshot::Sender<(String, Vec<u8>)>>,
41+
broadcast_handlers: HashMap<String, oneshot::Sender<MessagePayload>>,
4042

4143
/// Next batch collector ID.
4244
next_batch_id: u64,
@@ -62,7 +64,7 @@ impl Dispatcher {
6264
///
6365
/// Returns a `oneshot::Receiver` that resolves when a matching message arrives.
6466
/// The caller should wrap this with `tokio::time::timeout()`.
65-
pub fn register_handler(&mut self, command: &str) -> oneshot::Receiver<(String, Vec<u8>)> {
67+
pub fn register_handler(&mut self, command: &str) -> oneshot::Receiver<MessagePayload> {
6668
let (tx, rx) = oneshot::channel();
6769
self.pending
6870
.entry(command.to_string())
@@ -87,7 +89,7 @@ impl Dispatcher {
8789
pub fn register_any_handler(
8890
&mut self,
8991
commands: &[&str],
90-
) -> oneshot::Receiver<(String, Vec<u8>)> {
92+
) -> oneshot::Receiver<MessagePayload> {
9193
let (tx, rx) = oneshot::channel();
9294

9395
// We clone the sender for all but the last command.
@@ -168,7 +170,7 @@ impl Dispatcher {
168170
///
169171
/// The handler fires when a "reject" message arrives for this txid,
170172
/// or resolves to None (via timeout) if no reject = success.
171-
pub fn register_broadcast(&mut self, txid: &str) -> oneshot::Receiver<(String, Vec<u8>)> {
173+
pub fn register_broadcast(&mut self, txid: &str) -> oneshot::Receiver<MessagePayload> {
172174
let (tx, rx) = oneshot::channel();
173175
let key = format!("broadcast_{txid}");
174176
self.broadcast_handlers.insert(key, tx);

crates/zipherx-network/src/header_sync.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -292,10 +292,8 @@ impl<S: HeaderStore> HeaderSync<S> {
292292
let locator_hash = if let Some(hash) = last_known_hash {
293293
hash
294294
} else if current_height > 0 {
295-
match self.store.get_header_hash(current_height - 1)? {
296-
Some(hash) => hash,
297-
None => [0u8; 32],
298-
}
295+
self.store.get_header_hash(current_height - 1)?
296+
.unwrap_or([0u8; 32])
299297
} else {
300298
[0u8; 32]
301299
};
@@ -449,7 +447,7 @@ impl<S: HeaderStore> HeaderSync<S> {
449447
// RN-1: Verify every 10th header (10% coverage) instead of every
450448
// 100th (1%). This provides much better PoW verification coverage
451449
// with only a modest performance cost during bulk sync.
452-
let should_verify = remaining < 1000 || height % 10 == 0 || is_last_in_batch;
450+
let should_verify = remaining < 1000 || height.is_multiple_of(10) || is_last_in_batch;
453451

454452
if should_verify {
455453
match zipherx_crypto::equihash::verify(&header_base, &header.solution) {

crates/zipherx-network/src/peer.rs

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,17 @@ use crate::protocol;
2424
use crate::socks5;
2525
use crate::types::*;
2626

27+
/// Grouped listener callbacks passed to `block_listener_loop` and
28+
/// `handle_background_message` to avoid exceeding the argument limit.
29+
pub struct ListenerCallbacks {
30+
/// Callback fired when an unsolicited "tx" message arrives (mempool detection).
31+
pub on_mempool_tx_data: MempoolTxCallback,
32+
/// Callback fired when an inv MSG_BLOCK arrives (new block mined).
33+
pub on_new_block: NewBlockCallback,
34+
/// Callback fired when addr/addrv2 messages arrive with peer addresses.
35+
pub on_addr: AddrCallback,
36+
}
37+
2738
/// Maximum magic byte resyncs before declaring stream desync.
2839
const MAX_RESYNCS: usize = 5;
2940
/// Maximum bytes to scan for magic bytes during resync.
@@ -101,17 +112,17 @@ pub struct Peer {
101112
/// Wrapped in Arc<Mutex<>> so running block listeners share the same slot.
102113
/// When `set_on_mempool_tx_data` updates this, all running listeners see the change
103114
/// immediately — no need to restart listeners.
104-
pub on_mempool_tx_data: Arc<Mutex<Option<Arc<dyn Fn(Vec<u8>) + Send + Sync>>>>,
115+
pub on_mempool_tx_data: MempoolTxCallback,
105116

106117
/// Callback fired when an inv MSG_BLOCK arrives (new block mined).
107118
/// Signals the background sync loop to trigger an immediate sync instead
108119
/// of waiting for the 30s timer. Shared via Arc<Mutex<>> like on_mempool_tx_data.
109-
pub on_new_block: Arc<Mutex<Option<Arc<dyn Fn() + Send + Sync>>>>,
120+
pub on_new_block: NewBlockCallback,
110121

111122
/// Callback fired when addr/addrv2 messages arrive with peer addresses.
112123
/// Used for peer discovery — harvested addresses feed into PeerManager's
113124
/// known_addresses pool for future connections.
114-
pub on_addr: Arc<Mutex<Option<Arc<dyn Fn(Vec<(String, u16)>) + Send + Sync>>>>,
125+
pub on_addr: AddrCallback,
115126
}
116127

117128
impl Peer {
@@ -224,9 +235,11 @@ impl Peer {
224235
let cancel = CancellationToken::new();
225236
let cancel_clone = cancel.clone();
226237
let peer_id = self.id.clone();
227-
let on_mempool_tx_data = self.on_mempool_tx_data.clone(); // shares the same Mutex slot
228-
let on_new_block = self.on_new_block.clone();
229-
let on_addr = self.on_addr.clone();
238+
let callbacks = ListenerCallbacks {
239+
on_mempool_tx_data: self.on_mempool_tx_data.clone(), // shares the same Mutex slot
240+
on_new_block: self.on_new_block.clone(),
241+
on_addr: self.on_addr.clone(),
242+
};
230243

231244
let handle = tokio::spawn(async move {
232245
block_listener_loop(
@@ -235,9 +248,7 @@ impl Peer {
235248
dispatcher,
236249
cancel_clone,
237250
peer_id,
238-
on_mempool_tx_data,
239-
on_new_block,
240-
on_addr,
251+
callbacks,
241252
)
242253
.await;
243254
});
@@ -547,8 +558,8 @@ async fn do_handshake(
547558

548559
/// Check if a protocol version is valid Zclassic (not Zcash).
549560
fn is_valid_zclassic_version(version: u32) -> bool {
550-
(version >= MIN_PEER_PROTOCOL_VERSION && version <= MAX_ZCLASSIC_PROTOCOL_VERSION)
551-
|| (version >= ZCLASSIC_V2_MIN_VERSION && version <= ZCLASSIC_V2_MAX_VERSION)
561+
(MIN_PEER_PROTOCOL_VERSION..=MAX_ZCLASSIC_PROTOCOL_VERSION).contains(&version)
562+
|| (ZCLASSIC_V2_MIN_VERSION..=ZCLASSIC_V2_MAX_VERSION).contains(&version)
552563
}
553564

554565
/// Configure TCP keepalive and no-delay on a stream.
@@ -613,7 +624,7 @@ pub async fn receive_message_timeout(
613624
tokio::time::timeout(timeout, reader.read_exact(&mut payload))
614625
.await
615626
.map_err(|_| NetworkError::ResponseTimeout)?
616-
.map_err(|e| NetworkError::Io(e))?;
627+
.map_err(NetworkError::Io)?;
617628
}
618629

619630
// Verify checksum
@@ -682,9 +693,7 @@ async fn block_listener_loop(
682693
dispatcher: Arc<Mutex<Dispatcher>>,
683694
cancel: CancellationToken,
684695
peer_id: String,
685-
on_mempool_tx_data: Arc<Mutex<Option<Arc<dyn Fn(Vec<u8>) + Send + Sync>>>>,
686-
on_new_block: Arc<Mutex<Option<Arc<dyn Fn() + Send + Sync>>>>,
687-
on_addr: Arc<Mutex<Option<Arc<dyn Fn(Vec<(String, u16)>) + Send + Sync>>>>,
696+
callbacks: ListenerCallbacks,
688697
) {
689698
dispatcher.lock().unwrap().set_active(true);
690699

@@ -717,7 +726,7 @@ async fn block_listener_loop(
717726
eprintln!("[ZipherX] Peer {} exceeded rate limit ({} unsolicited msgs/min), disconnecting", peer_id, rl_count);
718727
break;
719728
}
720-
handle_background_message(&cmd, &payload, &writer, &peer_id, &on_mempool_tx_data, &on_new_block, &on_addr).await;
729+
handle_background_message(&cmd, &payload, &writer, &peer_id, &callbacks).await;
721730
}
722731
}
723732
Err(e) => {
@@ -739,15 +748,14 @@ async fn block_listener_loop(
739748
/// Event-driven mempool detection:
740749
/// - "inv" MSG_TX → immediately send getdata back to the peer
741750
/// - "tx" → fire `on_mempool_tx_data` callback with raw TX bytes
751+
///
742752
/// No separate task, no channel, no extra TCP connection.
743753
async fn handle_background_message(
744754
command: &str,
745755
payload: &[u8],
746756
writer: &Arc<Mutex<Option<OwnedWriteHalf>>>,
747757
_peer_id: &str,
748-
on_mempool_tx_data: &Arc<Mutex<Option<Arc<dyn Fn(Vec<u8>) + Send + Sync>>>>,
749-
on_new_block: &Arc<Mutex<Option<Arc<dyn Fn() + Send + Sync>>>>,
750-
on_addr: &Arc<Mutex<Option<Arc<dyn Fn(Vec<(String, u16)>) + Send + Sync>>>>,
758+
callbacks: &ListenerCallbacks,
751759
) {
752760
match command {
753761
// ── Keepalive ──
@@ -770,7 +778,7 @@ async fn handle_background_message(
770778
"[ZipherX] {}: inv MSG_BLOCK received — new block!",
771779
_peer_id
772780
);
773-
let cb = on_new_block.lock().unwrap().clone();
781+
let cb = callbacks.on_new_block.lock().unwrap().clone();
774782
if let Some(cb) = cb {
775783
cb();
776784
} else {
@@ -782,7 +790,7 @@ async fn handle_background_message(
782790
}
783791

784792
// MSG_TX: mempool detection — fetch TX for trial decryption
785-
if on_mempool_tx_data.lock().unwrap().is_some() {
793+
if callbacks.on_mempool_tx_data.lock().unwrap().is_some() {
786794
let tx_items: Vec<crate::types::InvVector> = items
787795
.into_iter()
788796
.filter(|item| item.inv_type == crate::types::InvType::Tx)
@@ -797,15 +805,15 @@ async fn handle_background_message(
797805

798806
// ── Transaction data (mempool detection) ──
799807
"tx" => {
800-
let cb = on_mempool_tx_data.lock().unwrap().clone();
808+
let cb = callbacks.on_mempool_tx_data.lock().unwrap().clone();
801809
if let Some(cb) = cb {
802810
cb(payload.to_vec());
803811
}
804812
}
805813

806814
// ── Peer address discovery ──
807815
"addr" => {
808-
let cb = on_addr.lock().unwrap().clone();
816+
let cb = callbacks.on_addr.lock().unwrap().clone();
809817
if let Some(cb) = cb {
810818
if let Some(addrs) = crate::messages::deserialize_addr(payload) {
811819
let peers: Vec<(String, u16)> = addrs
@@ -828,7 +836,7 @@ async fn handle_background_message(
828836
}
829837
}
830838
"addrv2" => {
831-
let cb = on_addr.lock().unwrap().clone();
839+
let cb = callbacks.on_addr.lock().unwrap().clone();
832840
if let Some(cb) = cb {
833841
if let Some(addrs) = crate::messages::deserialize_addrv2(payload) {
834842
let peers: Vec<(String, u16)> = addrs
@@ -953,7 +961,7 @@ mod tests {
953961
reader
954962
.read_exact(&mut header_buf)
955963
.await
956-
.map_err(|e| NetworkError::Io(e))?;
964+
.map_err(NetworkError::Io)?;
957965

958966
let (command, payload_len, checksum) = protocol::parse_header(&header_buf)?;
959967
let len = payload_len as usize;
@@ -962,7 +970,7 @@ mod tests {
962970
reader
963971
.read_exact(&mut payload)
964972
.await
965-
.map_err(|e| NetworkError::Io(e))?;
973+
.map_err(NetworkError::Io)?;
966974
}
967975
assert!(protocol::verify_checksum(&payload, &checksum));
968976
Ok((command, payload))

crates/zipherx-network/src/peer_manager.rs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ pub struct PeerManager {
194194
on_new_block: Option<Arc<dyn Fn() + Send + Sync>>,
195195

196196
/// Callback fired when addr/addrv2 messages arrive with peer addresses.
197-
on_addr: Option<Arc<dyn Fn(Vec<(String, u16)>) + Send + Sync>>,
197+
on_addr: Option<AddrCallbackFn>,
198198

199199
/// Live chain tip updated by block listener inv notifications.
200200
/// Tracks the minimum known chain height from inv MSG_BLOCK events.
@@ -265,7 +265,7 @@ impl PeerManager {
265265
}
266266

267267
/// Set the addr/addrv2 callback for peer discovery. Distributes to all existing peers.
268-
pub fn set_on_addr(&mut self, cb: Arc<dyn Fn(Vec<(String, u16)>) + Send + Sync>) {
268+
pub fn set_on_addr(&mut self, cb: AddrCallbackFn) {
269269
self.on_addr = Some(cb.clone());
270270
for peer in self.peers.values() {
271271
*peer.on_addr.lock().unwrap() = Some(cb.clone());
@@ -655,14 +655,7 @@ impl PeerManager {
655655
// Count peers within 10 blocks of median
656656
let consensus_count = heights
657657
.iter()
658-
.filter(|(_, h)| {
659-
let diff = if *h > median_height {
660-
*h - median_height
661-
} else {
662-
median_height - *h
663-
};
664-
diff <= 10
665-
})
658+
.filter(|(_, h)| (*h).abs_diff(median_height) <= 10)
666659
.count();
667660

668661
if consensus_count < 2 {
@@ -977,7 +970,7 @@ impl PeerManager {
977970
use tokio::sync::oneshot;
978971

979972
// Collect (peer_id, receiver) for all ready peers
980-
let mut receivers: Vec<(String, oneshot::Receiver<(String, Vec<u8>)>)> = Vec::new();
973+
let mut receivers: Vec<(String, oneshot::Receiver<MessagePayload>)> = Vec::new();
981974

982975
let ready_ids: Vec<String> = self
983976
.get_ready_peers()
@@ -1185,13 +1178,13 @@ fn is_reserved_ip(ip: &str) -> bool {
11851178
.split('.')
11861179
.nth(1)
11871180
.and_then(|s| s.parse::<u8>().ok())
1188-
.map_or(false, |n| (16..=31).contains(&n)))
1181+
.is_some_and(|n| (16..=31).contains(&n)))
11891182
|| (ip.starts_with("100.")
11901183
&& ip
11911184
.split('.')
11921185
.nth(1)
11931186
.and_then(|s| s.parse::<u8>().ok())
1194-
.map_or(false, |n| (64..=127).contains(&n)))
1187+
.is_some_and(|n| (64..=127).contains(&n)))
11951188
}
11961189

11971190
#[cfg(test)]

0 commit comments

Comments
 (0)