zebra_network/protocol/external/addr/
in_version.rs
1use std::{
7 io::{Read, Write},
8 net::SocketAddrV6,
9};
10
11use byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt};
12
13use zebra_chain::serialization::{
14 SerializationError, ZcashDeserialize, ZcashDeserializeInto, ZcashSerialize,
15};
16
17use crate::{protocol::external::types::PeerServices, PeerSocketAddr};
18
19#[cfg(any(test, feature = "proptest-impl"))]
20use proptest_derive::Arbitrary;
21
22#[cfg(any(test, feature = "proptest-impl"))]
23use crate::protocol::external::arbitrary::canonical_peer_addr_strategy;
24
25use super::{canonical_peer_addr, v1::ipv6_mapped_ip_addr};
26
27#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
32#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
33pub struct AddrInVersion {
34 untrusted_services: PeerServices,
44
45 #[cfg_attr(
50 any(test, feature = "proptest-impl"),
51 proptest(strategy = "canonical_peer_addr_strategy()")
52 )]
53 addr: PeerSocketAddr,
54}
55
56impl AddrInVersion {
57 pub fn new(socket_addr: impl Into<PeerSocketAddr>, untrusted_services: PeerServices) -> Self {
59 Self {
60 untrusted_services,
61 addr: canonical_peer_addr(socket_addr),
62 }
63 }
64
65 pub fn addr(&self) -> PeerSocketAddr {
67 self.addr
68 }
69
70 pub fn untrusted_services(&self) -> PeerServices {
72 self.untrusted_services
73 }
74}
75
76impl ZcashSerialize for AddrInVersion {
77 fn zcash_serialize<W: Write>(&self, mut writer: W) -> Result<(), std::io::Error> {
78 writer.write_u64::<LittleEndian>(self.untrusted_services.bits())?;
79
80 let ipv6_addr = ipv6_mapped_ip_addr(self.addr.ip());
81 ipv6_addr.zcash_serialize(&mut writer)?;
82 writer.write_u16::<BigEndian>(self.addr.port())?;
83
84 Ok(())
85 }
86}
87
88impl ZcashDeserialize for AddrInVersion {
89 fn zcash_deserialize<R: Read>(mut reader: R) -> Result<Self, SerializationError> {
90 let untrusted_services =
91 PeerServices::from_bits_truncate(reader.read_u64::<LittleEndian>()?);
92
93 let ipv6_addr = (&mut reader).zcash_deserialize_into()?;
94 let port = reader.read_u16::<BigEndian>()?;
95
96 let ipv6_addr = SocketAddrV6::new(ipv6_addr, port, 0, 0);
98
99 Ok(AddrInVersion {
100 addr: canonical_peer_addr(ipv6_addr),
101 untrusted_services,
102 })
103 }
104}