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