What changed, and why it matters
This commit is a routine code-quality cleanup for the rust-bitcoin peer-to-peer (p2p) crate. It switches the crate from its own custom Clippy lint rules to the shared workspace lint rules, and makes the matching style fixes: reformatting numeric literals, adding backticks to documentation links, replacing manual loops with references, and changing a couple of function signatures to take references instead of owned values. There is no security fix here.
No security action required. Treat as a normal refactoring/linting commit.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff removes per-crate Clippy lint overrides in p2p/Cargo.toml and enables workspace = true for lints. The source changes are purely mechanical responses to stricter/more consistent workspace lint rules: doc comment backtick formatting (e.g. [AddrV2Message] -> [AddrV2Message]), numeric literal underscores, redundant .to_vec() / .iter() cleanup, assert! rewrites of manual if-panic checks, and making UserAgentVersion parameters borrowed (&UserAgentVersion) in UserAgent constructors. The only behavioral-looking change is in CheckedData::consensus_decode where the success/error branches are reordered, but the logic is equivalent. No vulnerability is patched or introduced.
Changed components
p2p/Cargo.tomlp2p/examples/handshake.rsp2p/src/address.rsp2p/src/bip152.rsp2p/src/lib.rsp2p/src/message.rsp2p/src/message_blockdata.rsp2p/src/message_network.rsInspect captured patch +101 / −91
diff --git a/p2p/Cargo.toml b/p2p/Cargo.toml
index ee93bc22..2464eef9 100644
--- a/p2p/Cargo.toml
+++ b/p2p/Cargo.toml
@@ -39,6 +39,5 @@ required-features = ["std"]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
-[lints.clippy]
-redundant_clone = "warn"
-use_self = "warn"
+[lints]
+workspace = true
diff --git a/p2p/examples/handshake.rs b/p2p/examples/handshake.rs
index 690ffc06..d631b49f 100644
--- a/p2p/examples/handshake.rs
+++ b/p2p/examples/handshake.rs
@@ -101,7 +101,7 @@ fn build_version_message(address: SocketAddr) -> message::NetworkMessage {
let start_height: i32 = 0;
// A formatted string describing the software in use.
- let user_agent = UserAgent::new(SOFTWARE_NAME, USER_AGENT_VERSION);
+ let user_agent = UserAgent::new(SOFTWARE_NAME, &USER_AGENT_VERSION);
// Construct the message
message::NetworkMessage::Version(message_network::VersionMessage::new(
diff --git a/p2p/src/address.rs b/p2p/src/address.rs
index f04515b4..1cdfdc77 100644
--- a/p2p/src/address.rs
+++ b/p2p/src/address.rs
@@ -37,7 +37,7 @@ impl Address {
SocketAddr::V4(addr) => (addr.ip().to_ipv6_mapped().segments(), addr.port()),
SocketAddr::V6(addr) => (addr.ip().segments(), addr.port()),
};
- Self { address, port, services }
+ Self { services, address, port }
}
/// Builds a useless address that cannot be connected to. One may find this desirable if it is
@@ -101,7 +101,7 @@ fn read_be_address<R: Read + ?Sized>(r: &mut R) -> Result<[u16; 8], encode::Erro
for word in &mut address {
Read::read_exact(r, &mut buf)?;
- *word = u16::from_be_bytes(buf)
+ *word = u16::from_be_bytes(buf);
}
Ok(address)
}
@@ -320,7 +320,7 @@ pub struct AddrV2Message {
}
impl AddrV2Message {
- /// Extracts socket address from an [AddrV2Message] message.
+ /// Extracts socket address from an [`AddrV2Message`] message.
///
/// # Errors
///
@@ -800,7 +800,7 @@ mod test {
vec![
AddrV2Message {
services: ServiceFlags::NETWORK,
- time: 0x4966bc61,
+ time: 0x4966_bc61,
port: 8333,
addr: AddrV2::Unknown(153, hex!("abab").to_vec())
},
@@ -808,7 +808,7 @@ mod test {
services: ServiceFlags::NETWORK_LIMITED
| ServiceFlags::WITNESS
| ServiceFlags::COMPACT_FILTERS,
- time: 0x83766279,
+ time: 0x8376_6279,
port: 8333,
addr: AddrV2::Ipv4(Ipv4Addr::new(9, 9, 9, 9))
},
diff --git a/p2p/src/bip152.rs b/p2p/src/bip152.rs
index 27678594..448d6014 100644
--- a/p2p/src/bip152.rs
+++ b/p2p/src/bip152.rs
@@ -100,7 +100,11 @@ pub struct ShortId([u8; 6]);
internals::impl_array_newtype!(ShortId, u8, 6);
impl ShortId {
- /// Calculates the SipHash24 keys used to calculate short IDs.
+ /// Calculates the `SipHash24` keys used to calculate short IDs.
+ ///
+ /// # Panics
+ ///
+ /// Panics if consensus encoding fails (should never happen for in-memory operations).
pub fn calculate_siphash_keys(header: &block::Header, nonce: u64) -> (u64, u64) {
// 1. single-SHA256 hashing the block header with the nonce appended (in little-endian)
let h = {
@@ -118,7 +122,7 @@ impl ShortId {
)
}
- /// Calculates the short ID with the given (w)txid and using the provided SipHash keys.
+ /// Calculates the short ID with the given (w)txid and using the provided `SipHash` keys.
pub fn with_siphash_keys<T: TxIdentifier>(txid: &T, siphash_keys: (u64, u64)) -> Self {
// 2. Running SipHash-2-4 with the input being the transaction ID and the keys (k0/k1)
// set to the first two little-endian 64-bit integers from the above hash, respectively.
@@ -181,7 +185,7 @@ pub struct HeaderAndShortIds {
/// A nonce for use in short transaction ID calculations.
pub nonce: u64,
/// The short transaction IDs calculated from the transactions
- /// which were not provided explicitly in prefilled_txs.
+ /// which were not provided explicitly in `prefilled_txs`.
pub short_ids: Vec<ShortId>,
/// Used to provide the coinbase transaction and a select few
/// which we expect a peer may be missing.
@@ -225,6 +229,10 @@ impl HeaderAndShortIds {
/// coinbase tx is always prefilled.
///
/// > Nodes SHOULD NOT use the same nonce across multiple different blocks.
+ ///
+ /// # Errors
+ ///
+ /// Returns an error if the version is not 1 or 2, or if the prefill indexes are invalid.
pub fn from_block(
block: &Block<BlockChecked>,
nonce: u64,
@@ -405,6 +413,10 @@ crate::consensus::impl_consensus_encoding!(BlockTransactions, block_hash, transa
impl BlockTransactions {
/// Constructs a new [`BlockTransactions`] from a [`BlockTransactionsRequest`] and
/// the corresponding full [`Block`] by providing all requested transactions.
+ ///
+ /// # Errors
+ ///
+ /// Returns an error if any requested transaction index is out of range for the block.
pub fn from_request(
request: &BlockTransactionsRequest,
block: &Block<BlockChecked>,
@@ -534,7 +546,7 @@ mod test {
let block: Block = deserialize(&raw_block).unwrap();
let block = block.assume_checked(None);
- let nonce = 18053200567810711460;
+ let nonce = 18_053_200_567_810_711_460;
let compact = HeaderAndShortIds::from_block(&block, nonce, 2, &[]).unwrap();
let compact_expected = deserialize(&raw_compact).unwrap();
@@ -560,7 +572,7 @@ mod test {
// test deserialization
let mut raw: Vec<u8> = vec![0u8; 32];
raw.extend(testcase.0.clone());
- let btr: BlockTransactionsRequest = deserialize(&raw.to_vec()).unwrap();
+ let btr: BlockTransactionsRequest = deserialize(&raw.clone()).unwrap();
assert_eq!(testcase.1, btr.indexes);
}
{
@@ -579,14 +591,14 @@ mod test {
// test that we return Err() if deserialization fails (and don't panic)
let mut raw: Vec<u8> = [0u8; 32].to_vec();
raw.extend(errorcase);
- assert!(deserialize::<BlockTransactionsRequest>(&raw.to_vec()).is_err());
+ assert!(deserialize::<BlockTransactionsRequest>(&raw.clone()).is_err());
}
}
}
#[test]
#[cfg(debug_assertions)]
- #[should_panic] // 'attempt to add with overflow' in consensus_encode()
+ #[should_panic(expected = "attempt to add with overflow")]
fn getblocktx_panic_when_encoding_u64_max() {
serialize(&BlockTransactionsRequest {
block_hash: BlockHash::from_byte_array([0; 32]),
diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs
index c605bead..2d51fb45 100644
--- a/p2p/src/lib.rs
+++ b/p2p/src/lib.rs
@@ -7,12 +7,6 @@
#![warn(missing_docs)]
#![warn(deprecated_in_future)]
#![doc(test(attr(warn(unused))))]
-// Pedantic lints that we enforce.
-#![warn(clippy::return_self_not_must_use)]
-// Exclude lints we don't think are valuable.
-#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134
-#![allow(clippy::manual_range_contains)] // More readable than clippy's format.
-#![allow(clippy::uninlined_format_args)] // Allow `format!("{}", x)` instead of enforcing `format!("{x}")`
mod consensus;
mod network_ext;
@@ -68,9 +62,9 @@ pub use self::{address::Address, message::CheckedData};
/// 70014 - Support compact block messages `sendcmpct`, `cmpctblock`, `getblocktxn` and `blocktxn`
/// 70013 - Support `feefilter` message
/// 70012 - Support `sendheaders` message and announce new blocks via headers rather than inv
-/// 70011 - Support NODE_BLOOM service flag and don't support bloom filter messages if it is not set
+/// 70011 - Support `NODE_BLOOM` service flag and don't support bloom filter messages if it is not set
/// 70002 - Support `reject` message
-/// 70001 - Support bloom filter messages `filterload`, `filterclear` `filteradd`, `merkleblock` and FILTERED_BLOCK inventory type
+/// 70001 - Support bloom filter messages `filterload`, `filterclear` `filteradd`, `merkleblock` and `FILTERED_BLOCK` inventory type
/// 60002 - Support `mempool` message
/// 60001 - Support `pong` message and nonce in `ping` message
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -136,29 +130,29 @@ impl ServiceFlags {
/// BLOOM means the node is capable and willing to handle bloom-filtered connections. Bitcoin
/// Core nodes used to support this by default, without advertising this bit, but no longer do
- /// as of protocol version 70011 (= NO_BLOOM_VERSION)
+ /// as of protocol version 70011 (= `NO_BLOOM_VERSION`)
pub const BLOOM: Self = Self(1 << 2);
/// WITNESS indicates that a node can be asked for blocks and transactions including witness
/// data.
pub const WITNESS: Self = Self(1 << 3);
- /// COMPACT_FILTERS means the node will service basic block filter requests.
+ /// `COMPACT_FILTERS` means the node will service basic block filter requests.
/// See BIP-0157 and BIP-0158 for details on how this is implemented.
pub const COMPACT_FILTERS: Self = Self(1 << 6);
- /// NETWORK_LIMITED means the same as NODE_NETWORK with the limitation of only serving the last
+ /// `NETWORK_LIMITED` means the same as `NODE_NETWORK` with the limitation of only serving the last
/// 288 (2 day) blocks.
/// See BIP-0159 for details on how this is implemented.
pub const NETWORK_LIMITED: Self = Self(1 << 10);
- /// P2P_V2 indicates that the node supports the P2P v2 encrypted transport protocol.
+ /// `P2P_V2` indicates that the node supports the P2P v2 encrypted transport protocol.
/// See BIP-0324 for details on how this is implemented.
pub const P2P_V2: Self = Self(1 << 11);
// NOTE: When adding new flags, remember to update the Display impl accordingly.
- /// Add [ServiceFlags] together.
+ /// Add [`ServiceFlags`] together.
///
/// Returns itself.
#[must_use]
@@ -167,7 +161,7 @@ impl ServiceFlags {
*self
}
- /// Removes [ServiceFlags] from this.
+ /// Removes [`ServiceFlags`] from this.
///
/// Returns itself.
#[must_use]
@@ -176,7 +170,7 @@ impl ServiceFlags {
*self
}
- /// Checks whether [ServiceFlags] are included in this one.
+ /// Checks whether [`ServiceFlags`] are included in this one.
pub fn has(self, flags: Self) -> bool { (self.0 | flags.0) == self.0 }
/// Gets the integer representation of this [`ServiceFlags`].
@@ -321,7 +315,7 @@ impl TryFrom<Network> for Magic {
Network::Testnet(TestnetVersion::V4) => Ok(Self::TESTNET4),
Network::Signet => Ok(Self::SIGNET),
Network::Regtest => Ok(Self::REGTEST),
- _ => Err(UnknownNetworkError(network)),
+ Network::Testnet(_) => Err(UnknownNetworkError(network)),
}
}
}
@@ -540,7 +534,7 @@ mod tests {
];
let mut flags = ServiceFlags::NONE;
- for f in all.iter() {
+ for f in &all {
assert!(!flags.has(*f));
}
@@ -548,7 +542,7 @@ mod tests {
assert_eq!(flags, ServiceFlags::WITNESS);
let mut flags2 = flags | ServiceFlags::GETUTXO;
- for f in all.iter() {
+ for f in &all {
assert_eq!(flags2.has(*f), *f == ServiceFlags::WITNESS || *f == ServiceFlags::GETUTXO);
}
diff --git a/p2p/src/message.rs b/p2p/src/message.rs
index e0bf2f0b..cb692cf6 100644
--- a/p2p/src/message.rs
+++ b/p2p/src/message.rs
@@ -30,7 +30,7 @@ use crate::{
Magic,
};
-/// The maximum number of [super::message_blockdata::Inventory] items in an `inv` message.
+/// The maximum number of [`super::message_blockdata::Inventory`] items in an `inv` message.
///
/// This limit is not currently enforced by this implementation.
pub const MAX_INV_SIZE: usize = 50_000;
@@ -503,9 +503,9 @@ pub enum NetworkMessage {
impl NetworkMessage {
/// Returns the message command as a static string reference.
///
- /// This returns `"unknown"` for [NetworkMessage::Unknown],
+ /// This returns `"unknown"` for [`NetworkMessage::Unknown`],
/// regardless of the actual command in the unknown message.
- /// Use the [Self::command] method to get the command for unknown messages.
+ /// Use the [`Self::command`] method to get the command for unknown messages.
pub fn cmd(&self) -> &'static str {
match *self {
Self::Version(_) => "version",
@@ -548,7 +548,11 @@ impl NetworkMessage {
}
}
- /// Returns the CommandString for the message command.
+ /// Returns the `CommandString` for the message command.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the command string is invalid (should never happen for valid message types).
pub fn command(&self) -> CommandString {
match *self {
Self::Unknown { command: ref c, .. } => c.clone(),
@@ -558,7 +562,11 @@ impl NetworkMessage {
}
impl RawNetworkMessage {
- /// Constructs a new [RawNetworkMessage]
+ /// Constructs a new [`RawNetworkMessage`]
+ ///
+ /// # Panics
+ ///
+ /// Panics if message encoding fails or if the payload length exceeds `u32::MAX`.
pub fn new(magic: Magic, payload: NetworkMessage) -> Self {
let mut engine = sha256d::Hash::engine();
let payload_len = payload.consensus_encode(&mut engine).expect("engine doesn't error");
@@ -569,7 +577,7 @@ impl RawNetworkMessage {
Self { magic, payload, payload_len, checksum }
}
- /// Consumes the [RawNetworkMessage] instance and returns the inner payload.
+ /// Consumes the [`RawNetworkMessage`] instance and returns the inner payload.
pub fn into_payload(self) -> NetworkMessage { self.payload }
/// The actual message data
@@ -580,20 +588,20 @@ impl RawNetworkMessage {
/// Returns the message command as a static string reference.
///
- /// This returns `"unknown"` for [NetworkMessage::Unknown],
+ /// This returns `"unknown"` for [`NetworkMessage::Unknown`],
/// regardless of the actual command in the unknown message.
- /// Use the [Self::command] method to get the command for unknown messages.
+ /// Use the [`Self::command`] method to get the command for unknown messages.
pub fn cmd(&self) -> &'static str { self.payload.cmd() }
- /// Returns the CommandString for the message command.
+ /// Returns the `CommandString` for the message command.
pub fn command(&self) -> CommandString { self.payload.command() }
}
impl V2NetworkMessage {
- /// Constructs a new [V2NetworkMessage].
+ /// Constructs a new [`V2NetworkMessage`].
pub fn new(payload: NetworkMessage) -> Self { Self { payload } }
- /// Consumes the [V2NetworkMessage] instance and returns the inner payload.
+ /// Consumes the [`V2NetworkMessage`] instance and returns the inner payload.
pub fn into_payload(self) -> NetworkMessage { self.payload }
/// The actual message data
@@ -601,12 +609,12 @@ impl V2NetworkMessage {
/// Returns the message command as a static string reference.
///
- /// This returns `"unknown"` for [NetworkMessage::Unknown],
+ /// This returns `"unknown"` for [`NetworkMessage::Unknown`],
/// regardless of the actual command in the unknown message.
- /// Use the [Self::command] method to get the command for unknown messages.
+ /// Use the [`Self::command`] method to get the command for unknown messages.
pub fn cmd(&self) -> &'static str { self.payload.cmd() }
- /// Returns the CommandString for the message command.
+ /// Returns the `CommandString` for the message command.
pub fn command(&self) -> CommandString { self.payload.command() }
}
@@ -615,7 +623,7 @@ impl Encodable for HeadersMessage {
fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
let mut len = 0;
len += w.emit_compact_size(self.0.len())?;
- for header in self.0.iter() {
+ for header in &self.0 {
len += header.consensus_encode(w)?;
len += 0u8.consensus_encode(w)?;
}
@@ -766,6 +774,7 @@ impl encoding::Decoder for NetworkMessageDecoder {
Ok(self.buffer.len() < self.payload_len)
}
+ #[allow(clippy::too_many_lines)]
fn end(self) -> Result<Self::Output, Self::Error> {
let payload_bytes = self.buffer;
@@ -1076,9 +1085,8 @@ impl encoding::Decoder for RawNetworkMessageDecoder {
},
);
- let header_decoder = match old_state {
- DecoderState::ReadingHeader { header_decoder } => header_decoder,
- _ => unreachable!("we are in ReadingHeader state"),
+ let DecoderState::ReadingHeader { header_decoder } = old_state else {
+ unreachable!("we are in ReadingHeader state")
};
let (magic_bytes, command, payload_len_bytes, checksum) =
@@ -1512,14 +1520,14 @@ impl Decodable for CheckedData {
let opts = ReadBytesFromFiniteReaderOpts { len, chunk_size: encode::MAX_VEC_SIZE };
let data = read_bytes_from_finite_reader(r, opts)?;
let expected_checksum = sha2_checksum(&data);
- if expected_checksum != checksum {
+ if expected_checksum == checksum {
+ Ok(Self { data, checksum })
+ } else {
Err(encode::ParseError::InvalidChecksum {
expected: expected_checksum,
actual: checksum,
}
.into())
- } else {
- Ok(Self { data, checksum })
}
}
}
@@ -1674,6 +1682,7 @@ mod test {
fn hash(array: [u8; 32]) -> sha256d::Hash { sha256d::Hash::from_byte_array(array) }
#[test]
+ #[allow(clippy::too_many_lines)]
fn full_round_ser_der_raw_network_message() {
let version_msg: VersionMessage = deserialize(&hex!("721101000100000000000000e6e0845300000000010000000000000000000000000000000000ffff0000000000000100000000000000fd87d87eeb4364f22cf54dca59412db7208d47d920cffce83ee8102f5361746f7368693a302e392e39392f2c9f040001")).unwrap();
let tx: Transaction = deserialize(&hex!("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000")).unwrap();
@@ -1992,10 +2001,10 @@ mod test {
| ServiceFlags::WITNESS
| ServiceFlags::NETWORK_LIMITED
);
- assert_eq!(version_msg.timestamp, 1548554224);
- assert_eq!(version_msg.nonce, 13952548347456104954);
+ assert_eq!(version_msg.timestamp, 1_548_554_224);
+ assert_eq!(version_msg.nonce, 13_952_548_347_456_104_954);
assert_eq!(version_msg.user_agent.to_string(), "/Satoshi:0.17.1/");
- assert_eq!(version_msg.start_height, 560275);
+ assert_eq!(version_msg.start_height, 560_275);
assert!(version_msg.relay);
} else {
panic!("wrong message type");
@@ -2010,14 +2019,14 @@ mod test {
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, // "version" command
0x7f, 0x11, 0x01, 0x00, // version: 70015
0x0d, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // services
- 0xf0, 0x0f, 0x4d, 0x5c, 0x00, 0x00, 0x00, 0x00, // timestamp: 1548554224
+ 0xf0, 0x0f, 0x4d, 0x5c, 0x00, 0x00, 0x00, 0x00, // timestamp: 1_548_554_224
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // receiver services: NONE
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5b, 0xf0, 0x8c, 0x80, 0xb4, 0xbd, // addr_recv
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sender services: NONE
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // addr_from
0xfa, 0xa9, 0x95, 0x59, 0xcc, 0x68, 0xa1, 0xc1, // nonce
0x10, 0x2f, 0x53, 0x61, 0x74, 0x6f, 0x73, 0x68, 0x69, 0x3a, 0x30, 0x2e, 0x31, 0x37, 0x2e, 0x31, 0x2f, // user_agent: "/Satoshi:0.17.1/"
- 0x93, 0x8c, 0x08, 0x00, // start_height: 560275
+ 0x93, 0x8c, 0x08, 0x00, // start_height: 560_275
0x01 // relay: true
]).unwrap();
@@ -2030,10 +2039,10 @@ mod test {
| ServiceFlags::WITNESS
| ServiceFlags::NETWORK_LIMITED
);
- assert_eq!(version_msg.timestamp, 1548554224);
- assert_eq!(version_msg.nonce, 13952548347456104954);
+ assert_eq!(version_msg.timestamp, 1_548_554_224);
+ assert_eq!(version_msg.nonce, 13_952_548_347_456_104_954);
assert_eq!(version_msg.user_agent.to_string(), "/Satoshi:0.17.1/");
- assert_eq!(version_msg.start_height, 560275);
+ assert_eq!(version_msg.start_height, 560_275);
assert!(version_msg.relay);
} else {
panic!("wrong message type");
@@ -2076,10 +2085,10 @@ mod test {
| ServiceFlags::WITNESS
| ServiceFlags::NETWORK_LIMITED
);
- assert_eq!(version_msg.timestamp, 1548554224);
- assert_eq!(version_msg.nonce, 13952548347456104954);
+ assert_eq!(version_msg.timestamp, 1_548_554_224);
+ assert_eq!(version_msg.nonce, 13_952_548_347_456_104_954);
assert_eq!(version_msg.user_agent.to_string(), "/Satoshi:0.17.1/");
- assert_eq!(version_msg.start_height, 560275);
+ assert_eq!(version_msg.start_height, 560_275);
assert!(version_msg.relay);
} else {
panic!("wrong message type");
diff --git a/p2p/src/message_blockdata.rs b/p2p/src/message_blockdata.rs
index 788e4c00..10ac9e5c 100644
--- a/p2p/src/message_blockdata.rs
+++ b/p2p/src/message_blockdata.rs
@@ -47,7 +47,7 @@ pub enum Inventory {
impl Inventory {
/// Returns the item value represented as a SHA256-d hash.
///
- /// Returns [None] only for [Inventory::Error] who's hash value is meaningless.
+ /// Returns [None] only for [`Inventory::Error`] who's hash value is meaningless.
pub fn network_hash(&self) -> Option<[u8; 32]> {
match self {
Self::Error(_) => None,
@@ -76,8 +76,8 @@ impl Encodable for Inventory {
Self::Block(ref b) => encode_inv!(2, b),
Self::CompactBlock(ref b) => encode_inv!(4, b),
Self::WTx(ref w) => encode_inv!(5, w),
- Self::WitnessTransaction(ref t) => encode_inv!(0x40000001, t),
- Self::WitnessBlock(ref b) => encode_inv!(0x40000002, b),
+ Self::WitnessTransaction(ref t) => encode_inv!(0x4000_0001, t),
+ Self::WitnessBlock(ref b) => encode_inv!(0x4000_0002, b),
Self::Unknown { inv_type: t, hash: ref d } => encode_inv!(t, d),
})
}
@@ -93,8 +93,8 @@ impl Decodable for Inventory {
2 => Self::Block(Decodable::consensus_decode(r)?),
4 => Self::CompactBlock(Decodable::consensus_decode(r)?),
5 => Self::WTx(Decodable::consensus_decode(r)?),
- 0x40000001 => Self::WitnessTransaction(Decodable::consensus_decode(r)?),
- 0x40000002 => Self::WitnessBlock(Decodable::consensus_decode(r)?),
+ 0x4000_0001 => Self::WitnessTransaction(Decodable::consensus_decode(r)?),
+ 0x4000_0002 => Self::WitnessBlock(Decodable::consensus_decode(r)?),
tp => Self::Unknown { inv_type: tp, hash: Decodable::consensus_decode(r)? },
})
}
diff --git a/p2p/src/message_network.rs b/p2p/src/message_network.rs
index 58a43d67..5f364a32 100644
--- a/p2p/src/message_network.rs
+++ b/p2p/src/message_network.rs
@@ -109,15 +109,11 @@ impl UserAgent {
const MAX_USER_AGENT_LEN: usize = 256;
fn panic_invalid_chars(agent_str: &str) {
- if agent_str.chars().any(|c| matches!(c, '/' | '(' | ')' | ':')) {
- panic!("user agent configuration cannot contain: / ( ) :");
- }
+ assert!(!agent_str.chars().any(|c| matches!(c, '/' | '(' | ')' | ':')), "user agent configuration cannot contain: / ( ) :");
}
fn panic_max_len(agent_str: &str) {
- if agent_str.chars().count() > Self::MAX_USER_AGENT_LEN {
- panic!("user agent cannot exceed 256 characters.");
- }
+ assert!(agent_str.chars().count() <= Self::MAX_USER_AGENT_LEN, "user agent cannot exceed 256 characters.");
}
/// Builds a new user agent from the lowest level client software. For example: `Satoshi` is
/// used by Bitcoin Core.
@@ -125,7 +121,7 @@ impl UserAgent {
/// # Panics
///
/// If the client name contains one of: `/ ( ) :` or the user agent exceeds 256 characters.
- pub fn new<S: AsRef<str>>(client_name: S, client_version: UserAgentVersion) -> Self {
+ pub fn new<S: AsRef<str>>(client_name: S, client_version: &UserAgentVersion) -> Self {
let parsed_name = client_name.as_ref();
Self::panic_invalid_chars(parsed_name);
let agent = format!("/{parsed_name}:{client_version}/");
@@ -134,7 +130,7 @@ impl UserAgent {
}
/// Builds a user agent, ignoring BIP-0014 recommendations.
- pub fn from_nonstandard<S: ToString>(agent: S) -> Self {
+ pub fn from_nonstandard<S: ToString>(agent: &S) -> Self {
Self { user_agent: agent.to_string() }
}
@@ -147,7 +143,7 @@ impl UserAgent {
pub fn add_client<S: AsRef<str>>(
mut self,
client_name: S,
- client_version: UserAgentVersion,
+ client_version: &UserAgentVersion,
) -> Self {
let parsed_name = client_name.as_ref();
Self::panic_invalid_chars(parsed_name);
@@ -354,7 +350,7 @@ impl<'a> Arbitrary<'a> for UserAgentVersion {
#[cfg(feature = "arbitrary")]
impl<'a> Arbitrary<'a> for UserAgent {
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
- Ok(Self::new(u.arbitrary::<String>()?, u.arbitrary()?))
+ Ok(Self::new(u.arbitrary::<String>()?, &u.arbitrary()?))
}
}
@@ -428,21 +424,21 @@ mod tests {
let real_decode = decode.unwrap();
assert_eq!(real_decode.version.0, 70002);
assert_eq!(real_decode.services, ServiceFlags::NETWORK);
- assert_eq!(real_decode.timestamp, 1401217254);
+ assert_eq!(real_decode.timestamp, 1_401_217_254);
// address decodes should be covered by Address tests
- assert_eq!(real_decode.nonce, 16735069437859780935);
+ assert_eq!(real_decode.nonce, 16_735_069_437_859_780_935);
assert_eq!(
real_decode.user_agent,
UserAgent::new(
"Satoshi",
- UserAgentVersion::new(ClientSoftwareVersion::SemVer {
+ &UserAgentVersion::new(ClientSoftwareVersion::SemVer {
major: 0,
minor: 9,
revision: 99
})
)
);
- assert_eq!(real_decode.start_height, 302892);
+ assert_eq!(real_decode.start_height, 302_892);
assert!(real_decode.relay);
assert_eq!(serialize(&real_decode), from_sat);
@@ -500,7 +496,7 @@ mod tests {
minor: 12,
revision: 0,
});
- let user_agent = UserAgent::new(client_name, client_version);
+ let user_agent = UserAgent::new(client_name, &client_version);
assert_eq!("/Satoshi:5.12.0/", user_agent.to_string());
let wallet_name = "bitcoin-qt";
let wallet_version = UserAgentVersion::new(ClientSoftwareVersion::SemVer {
@@ -508,12 +504,12 @@ mod tests {
minor: 8,
revision: 0,
});
- let user_agent = user_agent.add_client(wallet_name, wallet_version);
+ let user_agent = user_agent.add_client(wallet_name, &wallet_version);
assert_eq!("/Satoshi:5.12.0/bitcoin-qt:0.8.0/", user_agent.to_string());
let client_name = "BitcoinJ";
let client_version =
UserAgentVersion::new(ClientSoftwareVersion::Date { yyyy: 2011, mm: 1, dd: 28 });
- let user_agent = UserAgent::new(client_name, client_version);
+ let user_agent = UserAgent::new(client_name, &client_version);
assert_eq!("/BitcoinJ:20110128/", user_agent.to_string());
let wallet_name = "Electrum";
let wallet_version = UserAgentVersion::new(ClientSoftwareVersion::SemVer {
@@ -523,12 +519,12 @@ mod tests {
});
let wallet_version = wallet_version.push_comment("Ubuntu");
let wallet_version = wallet_version.push_comment("24");
- let user_agent = user_agent.add_client(wallet_name, wallet_version);
+ let user_agent = user_agent.add_client(wallet_name, &wallet_version);
assert_eq!("/BitcoinJ:20110128/Electrum:0.9.0(Ubuntu; 24)/", user_agent.to_string());
}
#[test]
- #[should_panic]
+ #[should_panic(expected = "user agent configuration cannot contain: / ( ) :")]
fn test_incorrect_user_agent() {
let client_name = "Satoshi/";
let client_version = UserAgentVersion::new(ClientSoftwareVersion::SemVer {
@@ -536,6 +532,6 @@ mod tests {
minor: 12,
revision: 0,
});
- UserAgent::new(client_name, client_version);
+ UserAgent::new(client_name, &client_version);
}
}
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.