dig_peer_protocol/
introducer_wire.rs1use chia_protocol::TimestampedPeerInfo;
17use chia_streamable_macro::streamable;
18use chia_traits::Streamable;
19
20use crate::dig_message::DigMessage;
21use crate::dig_message_type::DigMessageType;
22use crate::node_type::NodeType;
23
24#[streamable(message)]
30pub struct RequestPeersIntroducer {}
31
32#[streamable(message)]
34pub struct RespondPeersIntroducer {
35 peer_list: Vec<TimestampedPeerInfo>,
36}
37
38#[streamable]
47pub struct RegisterPeer {
48 ip: String,
50 port: u16,
52 node_type: NodeType,
54}
55
56#[streamable]
60pub struct RegisterAck {
61 success: bool,
62}
63
64impl RegisterPeer {
65 pub fn to_dig_message(&self, id: Option<u16>) -> Result<DigMessage, chia_traits::Error> {
67 let data = self.to_bytes()?;
68 Ok(DigMessage::new(
69 DigMessageType::RegisterPeer as u8,
70 id,
71 data.into(),
72 ))
73 }
74
75 pub fn from_dig_message(msg: &DigMessage) -> Option<Result<Self, chia_traits::Error>> {
77 if msg.msg_type != DigMessageType::RegisterPeer as u8 {
78 return None;
79 }
80 Some(Self::from_bytes(&msg.data))
81 }
82}
83
84impl RegisterAck {
85 pub fn to_dig_message(&self, id: Option<u16>) -> Result<DigMessage, chia_traits::Error> {
87 let data = self.to_bytes()?;
88 Ok(DigMessage::new(
89 DigMessageType::RegisterAck as u8,
90 id,
91 data.into(),
92 ))
93 }
94
95 pub fn from_dig_message(msg: &DigMessage) -> Option<Result<Self, chia_traits::Error>> {
97 if msg.msg_type != DigMessageType::RegisterAck as u8 {
98 return None;
99 }
100 Some(Self::from_bytes(&msg.data))
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 #[test]
109 fn register_peer_round_trip() {
110 let rp = RegisterPeer::new("192.168.1.1".into(), 9444, NodeType::FullNode);
111 let msg = rp.to_dig_message(Some(42)).expect("encode");
112 assert_eq!(msg.msg_type, 218);
113 assert_eq!(msg.id, Some(42));
114
115 let decoded = RegisterPeer::from_dig_message(&msg)
116 .expect("correct opcode")
117 .expect("decode");
118 assert_eq!(decoded.ip, "192.168.1.1");
119 assert_eq!(decoded.port, 9444);
120 assert_eq!(decoded.node_type, NodeType::FullNode);
121 }
122
123 #[test]
124 fn register_ack_round_trip() {
125 let ack = RegisterAck::new(true);
126 let msg = ack.to_dig_message(None).expect("encode");
127 assert_eq!(msg.msg_type, 219);
128 assert_eq!(msg.id, None);
129
130 let decoded = RegisterAck::from_dig_message(&msg)
131 .expect("correct opcode")
132 .expect("decode");
133 assert!(decoded.success);
134 }
135
136 #[test]
137 fn wrong_opcode_returns_none() {
138 let msg = DigMessage::new(200, None, crate::Bytes::default());
139 assert!(RegisterPeer::from_dig_message(&msg).is_none());
140 assert!(RegisterAck::from_dig_message(&msg).is_none());
141 }
142
143 #[test]
144 fn request_peers_introducer_streamable() {
145 let req = RequestPeersIntroducer::new();
146 let bytes = req.to_bytes().expect("encode");
147 let _back = RequestPeersIntroducer::from_bytes(&bytes).expect("decode");
148 }
149
150 #[test]
151 fn respond_peers_introducer_streamable() {
152 let resp = RespondPeersIntroducer::new(vec![]);
153 let bytes = resp.to_bytes().expect("encode");
154 let back = RespondPeersIntroducer::from_bytes(&bytes).expect("decode");
155 assert!(back.peer_list.is_empty());
156 }
157
158 #[test]
159 fn respond_peers_introducer_with_populated_list_round_trips() {
160 let peers = vec![
164 TimestampedPeerInfo::new("203.0.113.7".into(), 9444, 1_700_000_000),
165 TimestampedPeerInfo::new("198.51.100.42".into(), 18444, 1_700_000_500),
166 ];
167 let resp = RespondPeersIntroducer::new(peers.clone());
168 let bytes = resp.to_bytes().expect("encode");
169 let back = RespondPeersIntroducer::from_bytes(&bytes).expect("decode");
170 assert_eq!(back.peer_list.len(), 2);
171 assert_eq!(back.peer_list, peers);
172 let other = vec![TimestampedPeerInfo::new("10.0.0.1".into(), 1, 1)];
174 assert_ne!(back.peer_list, other);
175 }
176
177 #[test]
178 fn register_peer_from_dig_message_decode_error() {
179 let bad = DigMessage::new(
183 DigMessageType::RegisterPeer as u8,
184 None,
185 crate::Bytes::new(vec![0xFF]), );
187 let result = RegisterPeer::from_dig_message(&bad);
188 let inner = result.expect("opcode matched, so we get Some(..)");
189 assert!(inner.is_err(), "corrupt body must surface a decode Err");
190 }
191
192 #[test]
193 fn register_ack_from_dig_message_decode_error() {
194 let bad = DigMessage::new(
196 DigMessageType::RegisterAck as u8,
197 None,
198 crate::Bytes::default(),
199 );
200 let result = RegisterAck::from_dig_message(&bad);
201 let inner = result.expect("opcode matched, so we get Some(..)");
202 assert!(
203 inner.is_err(),
204 "empty body must surface a decode Err for a bool field"
205 );
206 }
207
208 #[test]
209 fn register_ack_false_round_trips() {
210 let ack = RegisterAck::new(false);
212 let msg = ack.to_dig_message(Some(9)).expect("encode");
213 assert_eq!(msg.msg_type, 219);
214 assert_eq!(msg.id, Some(9));
215 let decoded = RegisterAck::from_dig_message(&msg)
216 .expect("correct opcode")
217 .expect("decode");
218 assert!(!decoded.success);
219 }
220}