zebra_network/protocol/external/addr/
v1.rs
1use std::{
9 io::{Read, Write},
10 net::{IpAddr, Ipv6Addr, SocketAddrV6},
11};
12
13use byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt};
14
15use zebra_chain::serialization::{
16 DateTime32, SerializationError, TrustedPreallocate, ZcashDeserialize, ZcashDeserializeInto,
17 ZcashSerialize,
18};
19
20use crate::{
21 meta_addr::MetaAddr,
22 protocol::external::{types::PeerServices, MAX_PROTOCOL_MESSAGE_LEN},
23 PeerSocketAddr,
24};
25
26use super::canonical_peer_addr;
27
28#[cfg(any(test, feature = "proptest-impl"))]
29use proptest_derive::Arbitrary;
30
31#[cfg(any(test, feature = "proptest-impl"))]
32use crate::protocol::external::arbitrary::canonical_peer_addr_strategy;
33
34#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
40#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
41pub(in super::super) struct AddrV1 {
42 untrusted_last_seen: DateTime32,
47
48 untrusted_services: PeerServices,
58
59 #[cfg_attr(
64 any(test, feature = "proptest-impl"),
65 proptest(strategy = "canonical_peer_addr_strategy()")
66 )]
67 addr: PeerSocketAddr,
68}
69
70impl From<MetaAddr> for AddrV1 {
71 fn from(meta_addr: MetaAddr) -> Self {
72 let addr = canonical_peer_addr(meta_addr.addr);
73
74 let untrusted_services = meta_addr.services.expect(
75 "unexpected MetaAddr with missing peer services: \
76 MetaAddrs should be sanitized before serialization",
77 );
78 let untrusted_last_seen = meta_addr.last_seen().expect(
79 "unexpected MetaAddr with missing last seen time: \
80 MetaAddrs should be sanitized before serialization",
81 );
82
83 AddrV1 {
84 untrusted_last_seen,
85 untrusted_services,
86 addr,
87 }
88 }
89}
90
91impl From<AddrV1> for MetaAddr {
92 fn from(addr: AddrV1) -> Self {
93 MetaAddr::new_gossiped_meta_addr(
94 addr.addr,
95 addr.untrusted_services,
96 addr.untrusted_last_seen,
97 )
98 }
99}
100
101impl ZcashSerialize for AddrV1 {
102 fn zcash_serialize<W: Write>(&self, mut writer: W) -> Result<(), std::io::Error> {
103 self.untrusted_last_seen.zcash_serialize(&mut writer)?;
104 writer.write_u64::<LittleEndian>(self.untrusted_services.bits())?;
105
106 let ipv6_addr = ipv6_mapped_ip_addr(self.addr.ip());
107 ipv6_addr.zcash_serialize(&mut writer)?;
108 writer.write_u16::<BigEndian>(self.addr.port())?;
109
110 Ok(())
111 }
112}
113
114impl ZcashDeserialize for AddrV1 {
115 fn zcash_deserialize<R: Read>(mut reader: R) -> Result<Self, SerializationError> {
116 let untrusted_last_seen = (&mut reader).zcash_deserialize_into()?;
117 let untrusted_services =
118 PeerServices::from_bits_truncate(reader.read_u64::<LittleEndian>()?);
119
120 let ipv6_addr = (&mut reader).zcash_deserialize_into()?;
121 let port = reader.read_u16::<BigEndian>()?;
122
123 let ipv6_addr = SocketAddrV6::new(ipv6_addr, port, 0, 0);
125
126 Ok(AddrV1 {
127 addr: canonical_peer_addr(ipv6_addr),
128 untrusted_services,
129 untrusted_last_seen,
130 })
131 }
132}
133
134pub(in super::super) const ADDR_V1_SIZE: usize = 4 + 8 + 16 + 2;
136
137impl TrustedPreallocate for AddrV1 {
138 fn max_allocation() -> u64 {
139 ((MAX_PROTOCOL_MESSAGE_LEN - 5) / ADDR_V1_SIZE) as u64
141 }
142}
143
144pub(in super::super) fn ipv6_mapped_ip_addr(ip_addr: IpAddr) -> Ipv6Addr {
150 use IpAddr::*;
151
152 match ip_addr {
153 V4(v4_addr) => v4_addr.to_ipv6_mapped(),
154 V6(v6_addr) => v6_addr,
155 }
156}