Move `p2p` encodings out of `encode`

All of the `Encodable` implementations are defined within `p2p` with the
exception of `p2p` types that are a `Vec`. To fully decouple `p2p` from
`encode` we can define these in `p2p` like the others. This is the final
step in removing anything `p2p` related from the rest of `bitcoin`.
This commit is contained in:
rustaceanrob 2025-05-27 14:24:18 +01:00
parent 94bcff28b1
commit 20779bdbc8
No known key found for this signature in database
GPG Key ID: F4DD8F8486EC0F1F
5 changed files with 65 additions and 35 deletions

View File

@ -26,11 +26,6 @@ use crate::bip152::{PrefilledTransaction, ShortId};
use crate::bip158::{FilterHash, FilterHeader};
use crate::block::{self, BlockHash};
use crate::merkle_tree::TxMerkleNode;
#[cfg(feature = "std")]
use crate::p2p::{
address::{AddrV2Message, Address},
message_blockdata::Inventory,
};
use crate::prelude::{rc, sync, Box, Cow, String, Vec};
use crate::taproot::TapLeafHash;
use crate::transaction::{Transaction, TxIn, TxOut};
@ -552,13 +547,6 @@ impl_vec!(TapLeafHash);
impl_vec!(ShortId);
impl_vec!(PrefilledTransaction);
#[cfg(feature = "std")]
impl_vec!(Inventory);
#[cfg(feature = "std")]
impl_vec!((u32, Address));
#[cfg(feature = "std")]
impl_vec!(AddrV2Message);
pub(crate) fn consensus_encode_with_size<W: Write + ?Sized>(
data: &[u8],
w: &mut W,
@ -765,8 +753,6 @@ mod tests {
use core::mem::discriminant;
use super::*;
#[cfg(feature = "std")]
use crate::p2p::{message_blockdata::Inventory, Address};
#[test]
fn serialize_int() {
@ -1049,10 +1035,6 @@ mod tests {
test_len_is_max_vec::<TxIn>();
test_len_is_max_vec::<Vec<u8>>();
test_len_is_max_vec::<u64>();
#[cfg(feature = "std")]
test_len_is_max_vec::<(u32, Address)>();
#[cfg(feature = "std")]
test_len_is_max_vec::<Inventory>();
}
fn test_len_is_max_vec<T>()

View File

@ -493,7 +493,7 @@ mod test {
use hex_lit::hex;
use super::*;
use crate::consensus::encode::{deserialize, serialize};
use crate::{consensus::encode::{deserialize, serialize}, p2p::message::AddrV2Payload};
#[test]
fn serialize_address() {
@ -706,10 +706,10 @@ mod test {
#[test]
fn addrv2message() {
let raw = hex!("0261bc6649019902abab208d79627683fd4804010409090909208d");
let addresses: Vec<AddrV2Message> = deserialize(&raw).unwrap();
let addresses: AddrV2Payload = deserialize(&raw).unwrap();
assert_eq!(
addresses,
addresses.0,
vec![
AddrV2Message {
services: ServiceFlags::NETWORK,

41
bitcoin/src/p2p/deser.rs Normal file
View File

@ -0,0 +1,41 @@
macro_rules! impl_vec_wrapper {
($wrapper: ident, $type: ty) => {
impl crate::consensus::encode::Encodable for $wrapper {
#[inline]
fn consensus_encode<W: io::Write + ?Sized>(
&self,
w: &mut W,
) -> core::result::Result<usize, io::Error> {
let mut len = 0;
len += w.emit_compact_size(self.0.len())?;
for c in self.0.iter() {
len += c.consensus_encode(w)?;
}
Ok(len)
}
}
impl crate::consensus::encode::Decodable for $wrapper {
#[inline]
fn consensus_decode_from_finite_reader<R: io::BufRead + ?Sized>(
r: &mut R,
) -> core::result::Result<$wrapper, crate::consensus::encode::Error> {
let len = r.read_compact_size()?;
// Do not allocate upfront more items than if the sequence of type
// occupied roughly quarter a block. This should never be the case
// for normal data, but even if that's not true - `push` will just
// reallocate.
// Note: OOM protection relies on reader eventually running out of
// data to feed us.
let max_capacity = crate::consensus::encode::MAX_VEC_SIZE / 4 / core::mem::size_of::<$type>();
let mut ret = Vec::with_capacity(core::cmp::min(len as usize, max_capacity));
for _ in 0..len {
ret.push(Decodable::consensus_decode_from_finite_reader(r)?);
}
Ok($wrapper(ret))
}
}
};
}
pub(crate) use impl_vec_wrapper;

View File

@ -19,6 +19,7 @@ use crate::p2p::{
Magic,
};
use crate::prelude::{Box, Cow, String, ToOwned, Vec};
use crate::p2p::deser::impl_vec_wrapper;
use crate::{block, consensus, transaction};
/// The maximum number of [super::message_blockdata::Inventory] items in an `inv` message.
@ -175,6 +176,10 @@ pub struct AddrPayload(pub Vec<(u32, Address)>);
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct AddrV2Payload(pub Vec<AddrV2Message>);
impl_vec_wrapper!(InventoryPayload, message_blockdata::Inventory);
impl_vec_wrapper!(AddrPayload, (u32, Address));
impl_vec_wrapper!(AddrV2Payload, AddrV2Message);
/// A Network message payload. Proper documentation is available on at
/// [Bitcoin Wiki: Protocol Specification](https://en.bitcoin.it/wiki/Protocol_specification)
#[derive(Clone, PartialEq, Eq, Debug)]
@ -184,13 +189,13 @@ pub enum NetworkMessage {
/// `verack`
Verack,
/// `addr`
Addr(Vec<(u32, Address)>),
Addr(AddrPayload),
/// `inv`
Inv(Vec<message_blockdata::Inventory>),
Inv(InventoryPayload),
/// `getdata`
GetData(Vec<message_blockdata::Inventory>),
GetData(InventoryPayload),
/// `notfound`
NotFound(Vec<message_blockdata::Inventory>),
NotFound(InventoryPayload),
/// `getblocks`
GetBlocks(message_blockdata::GetBlocksMessage),
/// `getheaders`
@ -248,7 +253,7 @@ pub enum NetworkMessage {
/// `wtxidrelay`
WtxidRelay,
/// `addrv2`
AddrV2(Vec<AddrV2Message>),
AddrV2(AddrV2Payload),
/// `sendaddrv2`
SendAddrV2,
@ -746,17 +751,17 @@ mod test {
let msgs = [
NetworkMessage::Version(version_msg),
NetworkMessage::Verack,
NetworkMessage::Addr(vec![(
NetworkMessage::Addr(AddrPayload(vec![(
45,
Address::new(&([123, 255, 000, 100], 833).into(), ServiceFlags::NETWORK),
)]),
NetworkMessage::Inv(vec![Inventory::Block(BlockHash::from_byte_array(
)])),
NetworkMessage::Inv(InventoryPayload(vec![Inventory::Block(BlockHash::from_byte_array(
hash([8u8; 32]).to_byte_array(),
))]),
NetworkMessage::GetData(vec![Inventory::Transaction(Txid::from_byte_array(
))])),
NetworkMessage::GetData(InventoryPayload(vec![Inventory::Transaction(Txid::from_byte_array(
hash([45u8; 32]).to_byte_array(),
))]),
NetworkMessage::NotFound(vec![Inventory::Error([0u8; 32])]),
))])),
NetworkMessage::NotFound(InventoryPayload(vec![Inventory::Error([0u8; 32])])),
NetworkMessage::GetBlocks(GetBlocksMessage::new(
vec![
BlockHash::from_byte_array(hash([1u8; 32]).to_byte_array()),
@ -838,12 +843,12 @@ mod test {
}),
NetworkMessage::FeeFilter(1000),
NetworkMessage::WtxidRelay,
NetworkMessage::AddrV2(vec![AddrV2Message {
NetworkMessage::AddrV2(AddrV2Payload(vec![AddrV2Message {
addr: AddrV2::Ipv4(Ipv4Addr::new(127, 0, 0, 1)),
port: 0,
services: ServiceFlags::NONE,
time: 0,
}]),
}])),
NetworkMessage::SendAddrV2,
NetworkMessage::CmpctBlock(cmptblock),
NetworkMessage::GetBlockTxn(GetBlockTxn {

View File

@ -19,6 +19,8 @@ pub mod message_compact_blocks;
pub mod message_filter;
#[cfg(feature = "std")]
pub mod message_network;
#[cfg(feature = "std")]
mod deser;
use core::str::FromStr;
use core::{fmt, ops};