Merge rust-bitcoin/rust-bitcoin#4571: Move `p2p` encodings from `encode` and into `p2p`
20779bdbc8
Move `p2p` encodings out of `encode` (rustaceanrob)94bcff28b1
p2p: Add wrappers for messages that use `Vec` (rustaceanrob) Pull request description: To move `p2p` into a crate: 1. All `Encodable` implementations for `p2p` must be defined in `p2p`. To accomplish this, and anything else in the future related to encoding, I added a `deser` module with the necessary macro to implement `Encodable` for `Vec<T> where T: Encodable`. 2. Because the orphan rule would apply for implementing `Encodable`for `Vec` within `p2p`, three types defined within `p2p` are used to wrap the `Vec` and snake around the orphan rule. ACKs for top commit: tcharding: ACK20779bdbc8
apoelstra: ACK 20779bdbc8ebcac2365d122e857c23b3d8e8d1e7; successfully ran local tests Tree-SHA512: 7abfe5b853e84bb465579309f80a0687c325217f6f342651278bedf540c4d17ae16683ab02dea5e3d98d90790deb12c6bc7d572a92cec8e19ff94e395bc0d29c
This commit is contained in:
commit
2113a32276
|
@ -26,11 +26,6 @@ use crate::bip152::{PrefilledTransaction, ShortId};
|
||||||
use crate::bip158::{FilterHash, FilterHeader};
|
use crate::bip158::{FilterHash, FilterHeader};
|
||||||
use crate::block::{self, BlockHash};
|
use crate::block::{self, BlockHash};
|
||||||
use crate::merkle_tree::TxMerkleNode;
|
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::prelude::{rc, sync, Box, Cow, String, Vec};
|
||||||
use crate::taproot::TapLeafHash;
|
use crate::taproot::TapLeafHash;
|
||||||
use crate::transaction::{Transaction, TxIn, TxOut};
|
use crate::transaction::{Transaction, TxIn, TxOut};
|
||||||
|
@ -552,13 +547,6 @@ impl_vec!(TapLeafHash);
|
||||||
impl_vec!(ShortId);
|
impl_vec!(ShortId);
|
||||||
impl_vec!(PrefilledTransaction);
|
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>(
|
pub(crate) fn consensus_encode_with_size<W: Write + ?Sized>(
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
w: &mut W,
|
w: &mut W,
|
||||||
|
@ -765,8 +753,6 @@ mod tests {
|
||||||
use core::mem::discriminant;
|
use core::mem::discriminant;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
#[cfg(feature = "std")]
|
|
||||||
use crate::p2p::{message_blockdata::Inventory, Address};
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_int() {
|
fn serialize_int() {
|
||||||
|
@ -1049,10 +1035,6 @@ mod tests {
|
||||||
test_len_is_max_vec::<TxIn>();
|
test_len_is_max_vec::<TxIn>();
|
||||||
test_len_is_max_vec::<Vec<u8>>();
|
test_len_is_max_vec::<Vec<u8>>();
|
||||||
test_len_is_max_vec::<u64>();
|
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>()
|
fn test_len_is_max_vec<T>()
|
||||||
|
|
|
@ -443,7 +443,7 @@ mod test {
|
||||||
use hex_lit::hex;
|
use hex_lit::hex;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::consensus::encode::{deserialize, serialize};
|
use crate::{consensus::encode::{deserialize, serialize}, p2p::message::AddrV2Payload};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_address() {
|
fn serialize_address() {
|
||||||
|
@ -656,10 +656,10 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn addrv2message() {
|
fn addrv2message() {
|
||||||
let raw = hex!("0261bc6649019902abab208d79627683fd4804010409090909208d");
|
let raw = hex!("0261bc6649019902abab208d79627683fd4804010409090909208d");
|
||||||
let addresses: Vec<AddrV2Message> = deserialize(&raw).unwrap();
|
let addresses: AddrV2Payload = deserialize(&raw).unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
addresses,
|
addresses.0,
|
||||||
vec![
|
vec![
|
||||||
AddrV2Message {
|
AddrV2Message {
|
||||||
services: ServiceFlags::NETWORK,
|
services: ServiceFlags::NETWORK,
|
||||||
|
|
|
@ -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;
|
|
@ -19,6 +19,7 @@ use crate::p2p::{
|
||||||
Magic,
|
Magic,
|
||||||
};
|
};
|
||||||
use crate::prelude::{Box, Cow, String, ToOwned, Vec};
|
use crate::prelude::{Box, Cow, String, ToOwned, Vec};
|
||||||
|
use crate::p2p::deser::impl_vec_wrapper;
|
||||||
use crate::{block, consensus, transaction};
|
use crate::{block, consensus, transaction};
|
||||||
|
|
||||||
/// 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.
|
||||||
|
@ -163,6 +164,22 @@ pub struct V2NetworkMessage {
|
||||||
payload: NetworkMessage,
|
payload: NetworkMessage,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A list of inventory items.
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
|
pub struct InventoryPayload(pub Vec<message_blockdata::Inventory>);
|
||||||
|
|
||||||
|
/// A list of legacy p2p address messages.
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
|
pub struct AddrPayload(pub Vec<(u32, Address)>);
|
||||||
|
|
||||||
|
/// A list of v2 address messages.
|
||||||
|
#[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
|
/// A Network message payload. Proper documentation is available on at
|
||||||
/// [Bitcoin Wiki: Protocol Specification](https://en.bitcoin.it/wiki/Protocol_specification)
|
/// [Bitcoin Wiki: Protocol Specification](https://en.bitcoin.it/wiki/Protocol_specification)
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
|
@ -172,13 +189,13 @@ pub enum NetworkMessage {
|
||||||
/// `verack`
|
/// `verack`
|
||||||
Verack,
|
Verack,
|
||||||
/// `addr`
|
/// `addr`
|
||||||
Addr(Vec<(u32, Address)>),
|
Addr(AddrPayload),
|
||||||
/// `inv`
|
/// `inv`
|
||||||
Inv(Vec<message_blockdata::Inventory>),
|
Inv(InventoryPayload),
|
||||||
/// `getdata`
|
/// `getdata`
|
||||||
GetData(Vec<message_blockdata::Inventory>),
|
GetData(InventoryPayload),
|
||||||
/// `notfound`
|
/// `notfound`
|
||||||
NotFound(Vec<message_blockdata::Inventory>),
|
NotFound(InventoryPayload),
|
||||||
/// `getblocks`
|
/// `getblocks`
|
||||||
GetBlocks(message_blockdata::GetBlocksMessage),
|
GetBlocks(message_blockdata::GetBlocksMessage),
|
||||||
/// `getheaders`
|
/// `getheaders`
|
||||||
|
@ -236,7 +253,7 @@ pub enum NetworkMessage {
|
||||||
/// `wtxidrelay`
|
/// `wtxidrelay`
|
||||||
WtxidRelay,
|
WtxidRelay,
|
||||||
/// `addrv2`
|
/// `addrv2`
|
||||||
AddrV2(Vec<AddrV2Message>),
|
AddrV2(AddrV2Payload),
|
||||||
/// `sendaddrv2`
|
/// `sendaddrv2`
|
||||||
SendAddrV2,
|
SendAddrV2,
|
||||||
|
|
||||||
|
@ -734,17 +751,17 @@ mod test {
|
||||||
let msgs = [
|
let msgs = [
|
||||||
NetworkMessage::Version(version_msg),
|
NetworkMessage::Version(version_msg),
|
||||||
NetworkMessage::Verack,
|
NetworkMessage::Verack,
|
||||||
NetworkMessage::Addr(vec![(
|
NetworkMessage::Addr(AddrPayload(vec![(
|
||||||
45,
|
45,
|
||||||
Address::new(&([123, 255, 000, 100], 833).into(), ServiceFlags::NETWORK),
|
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(),
|
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(),
|
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(
|
NetworkMessage::GetBlocks(GetBlocksMessage::new(
|
||||||
vec![
|
vec![
|
||||||
BlockHash::from_byte_array(hash([1u8; 32]).to_byte_array()),
|
BlockHash::from_byte_array(hash([1u8; 32]).to_byte_array()),
|
||||||
|
@ -826,12 +843,12 @@ mod test {
|
||||||
}),
|
}),
|
||||||
NetworkMessage::FeeFilter(1000),
|
NetworkMessage::FeeFilter(1000),
|
||||||
NetworkMessage::WtxidRelay,
|
NetworkMessage::WtxidRelay,
|
||||||
NetworkMessage::AddrV2(vec![AddrV2Message {
|
NetworkMessage::AddrV2(AddrV2Payload(vec![AddrV2Message {
|
||||||
addr: AddrV2::Ipv4(Ipv4Addr::new(127, 0, 0, 1)),
|
addr: AddrV2::Ipv4(Ipv4Addr::new(127, 0, 0, 1)),
|
||||||
port: 0,
|
port: 0,
|
||||||
services: ServiceFlags::NONE,
|
services: ServiceFlags::NONE,
|
||||||
time: 0,
|
time: 0,
|
||||||
}]),
|
}])),
|
||||||
NetworkMessage::SendAddrV2,
|
NetworkMessage::SendAddrV2,
|
||||||
NetworkMessage::CmpctBlock(cmptblock),
|
NetworkMessage::CmpctBlock(cmptblock),
|
||||||
NetworkMessage::GetBlockTxn(GetBlockTxn {
|
NetworkMessage::GetBlockTxn(GetBlockTxn {
|
||||||
|
|
|
@ -19,6 +19,8 @@ pub mod message_compact_blocks;
|
||||||
pub mod message_filter;
|
pub mod message_filter;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub mod message_network;
|
pub mod message_network;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
mod deser;
|
||||||
|
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
use core::{fmt, ops};
|
use core::{fmt, ops};
|
||||||
|
|
Loading…
Reference in New Issue