1#![warn(missing_docs)]
2
3use std::io::Write;
4use std::sync::Arc;
5
6use async_trait::async_trait;
7use bytes::Bytes;
8use derivative::Derivative;
9use flate2::write::GzDecoder;
10use flate2::write::GzEncoder;
11use flate2::Compression;
12use serde::de::DeserializeOwned;
13use serde::Deserialize;
14use serde::Serialize;
15
16use super::encoder::Decoder;
17use super::encoder::Encoded;
18use super::encoder::Encoder;
19use super::protocols::MessageRelay;
20use super::protocols::MessageVerification;
21use super::protocols::MessageVerificationExt;
22use crate::dht::Chord;
23use crate::dht::Did;
24use crate::dht::PeerRing;
25use crate::dht::PeerRingAction;
26use crate::ecc::keccak256;
27use crate::error::Error;
28use crate::error::Result;
29use crate::session::SessionSk;
30
31pub fn encode_data_gzip(data: &Bytes, level: u8) -> Result<Bytes> {
33 let mut ec = GzEncoder::new(Vec::new(), Compression::new(level as u32));
34 tracing::info!("data before gzip len: {}", data.len());
35 ec.write_all(data).map_err(|_| Error::GzipEncode)?;
36 ec.finish().map(Bytes::from).map_err(|_| Error::GzipEncode)
37}
38
39pub fn gzip_data<T>(data: &T, level: u8) -> Result<Bytes>
41where T: Serialize {
42 let json_bytes = serde_json::to_vec(data).map_err(|_| Error::SerializeToString)?;
43 encode_data_gzip(&json_bytes.into(), level)
44}
45
46pub fn decode_gzip_data(data: &Bytes) -> Result<Bytes> {
48 let mut writer = Vec::new();
49 let mut decoder = GzDecoder::new(writer);
50 decoder.write_all(data).map_err(|_| Error::GzipDecode)?;
51 decoder.try_finish().map_err(|_| Error::GzipDecode)?;
52 writer = decoder.finish().map_err(|_| Error::GzipDecode)?;
53 Ok(writer.into())
54}
55
56pub fn from_gzipped_data<T>(data: &Bytes) -> Result<T>
58where T: DeserializeOwned {
59 let data = decode_gzip_data(data)?;
60 let m = serde_json::from_slice(&data).map_err(Error::Deserialize)?;
61 Ok(m)
62}
63
64fn hash_transaction(destination: Did, tx_id: uuid::Uuid, data: &[u8]) -> [u8; 32] {
65 let mut msg = vec![];
66
67 msg.extend_from_slice(destination.as_bytes());
68 msg.extend_from_slice(tx_id.as_bytes());
69 msg.extend_from_slice(data);
70
71 keccak256(&msg)
72}
73
74#[derive(Derivative, Deserialize, Serialize, Clone, PartialEq, Eq)]
80#[derivative(Debug)]
81pub struct Transaction {
82 pub destination: Did,
84 pub tx_id: uuid::Uuid,
87 pub data: Vec<u8>,
89 #[derivative(Debug = "ignore")]
92 pub verification: MessageVerification,
93}
94
95#[derive(Derivative, Deserialize, Serialize, Clone, PartialEq, Eq)]
98#[derivative(Debug)]
99pub struct MessagePayload {
100 pub transaction: Transaction,
102 pub relay: MessageRelay,
105 #[derivative(Debug = "ignore")]
108 pub verification: MessageVerification,
109}
110
111impl Transaction {
112 pub fn new<T>(
115 destination: Did,
116 tx_id: uuid::Uuid,
117 data: T,
118 session_sk: &SessionSk,
119 ) -> Result<Self>
120 where
121 T: Serialize,
122 {
123 let data = bincode::serialize(&data).map_err(Error::BincodeSerialize)?;
124 let msg_hash = hash_transaction(destination, tx_id, &data);
125 let verification = MessageVerification::new(&msg_hash, session_sk)?;
126 Ok(Self {
127 destination,
128 tx_id,
129 data,
130 verification,
131 })
132 }
133
134 pub fn data<T>(&self) -> Result<T>
136 where T: DeserializeOwned {
137 bincode::deserialize(&self.data).map_err(Error::BincodeDeserialize)
138 }
139}
140
141impl MessagePayload {
142 pub fn new(
145 transaction: Transaction,
146 session_sk: &SessionSk,
147 relay: MessageRelay,
148 ) -> Result<Self> {
149 let msg_hash = hash_transaction(
150 transaction.destination,
151 transaction.tx_id,
152 &transaction.data,
153 );
154 let verification = MessageVerification::new(&msg_hash, session_sk)?;
155 Ok(Self {
156 transaction,
157 relay,
158 verification,
159 })
160 }
161
162 pub fn new_send<T>(
164 data: T,
165 session_sk: &SessionSk,
166 next_hop: Did,
167 destination: Did,
168 ) -> Result<Self>
169 where
170 T: Serialize,
171 {
172 let tx_id = uuid::Uuid::new_v4();
173 let transaction = Transaction::new(destination, tx_id, data, session_sk)?;
174 let relay = MessageRelay::new(
175 vec![session_sk.account_did()],
176 next_hop,
177 transaction.destination,
178 );
179 Self::new(transaction, session_sk, relay)
180 }
181
182 pub fn from_bincode(data: &[u8]) -> Result<Self> {
184 bincode::deserialize(data).map_err(Error::BincodeDeserialize)
185 }
186
187 pub fn to_bincode(&self) -> Result<Bytes> {
189 bincode::serialize(self)
190 .map(Bytes::from)
191 .map_err(Error::BincodeSerialize)
192 }
193
194 pub(crate) fn is_relay_destination_for(&self, local: Did) -> bool {
196 self.relay.destination == local
197 }
198
199 pub(crate) fn should_forward_from(&self, local: Did) -> bool {
201 !self.is_relay_destination_for(local)
202 }
203}
204
205impl MessageVerificationExt for Transaction {
206 fn verification_data(&self) -> Result<Vec<u8>> {
207 Ok(hash_transaction(self.destination, self.tx_id, &self.data).to_vec())
208 }
209
210 fn verification(&self) -> &MessageVerification {
211 &self.verification
212 }
213}
214
215impl MessageVerificationExt for MessagePayload {
216 fn verification_data(&self) -> Result<Vec<u8>> {
217 Ok(hash_transaction(
218 self.transaction.destination,
219 self.transaction.tx_id,
220 &self.transaction.data,
221 )
222 .to_vec())
223 }
224
225 fn verification(&self) -> &MessageVerification {
226 &self.verification
227 }
228}
229
230impl Encoder for MessagePayload {
231 fn encode(&self) -> Result<Encoded> {
232 self.to_bincode()?.encode()
233 }
234}
235
236impl Decoder for MessagePayload {
237 fn from_encoded(encoded: &Encoded) -> Result<Self> {
238 let v: Bytes = encoded.decode()?;
239 Self::from_bincode(&v)
240 }
241}
242
243#[cfg_attr(feature = "wasm", async_trait(?Send))]
245#[cfg_attr(not(feature = "wasm"), async_trait)]
246pub trait PayloadSender {
247 fn session_sk(&self) -> &SessionSk;
249
250 fn dht(&self) -> Arc<PeerRing>;
252
253 fn is_connected(&self, did: Did) -> bool;
255
256 async fn do_send_payload(&self, did: Did, payload: MessagePayload) -> Result<()>;
258
259 fn infer_next_hop(&self, destination: Did, next_hop: Option<Did>) -> Result<Did> {
261 if self.is_connected(destination) {
262 return Ok(destination);
263 }
264
265 if let Some(next_hop) = next_hop {
266 return Ok(next_hop);
267 }
268
269 match self.dht().find_successor(destination)? {
270 PeerRingAction::Some(did) => Ok(did),
271 PeerRingAction::RemoteAction(did, _) => Ok(did),
272 _ => Err(Error::NoNextHop),
273 }
274 }
275
276 async fn send_payload(&self, payload: MessagePayload) -> Result<()> {
278 self.do_send_payload(payload.relay.next_hop, payload).await
279 }
280
281 async fn send_message_by_hop<T>(
283 &self,
284 msg: T,
285 destination: Did,
286 next_hop: Did,
287 ) -> Result<uuid::Uuid>
288 where
289 T: Serialize + Send,
290 {
291 let payload = MessagePayload::new_send(msg, self.session_sk(), next_hop, destination)?;
292 let tx_id = payload.transaction.tx_id;
293 self.send_payload(payload).await?;
294 Ok(tx_id)
295 }
296
297 async fn send_message<T>(&self, msg: T, destination: Did) -> Result<uuid::Uuid>
299 where T: Serialize + Send {
300 let next_hop = self.infer_next_hop(destination, None)?;
301 self.send_message_by_hop(msg, destination, next_hop).await
302 }
303
304 async fn send_direct_message<T>(&self, msg: T, destination: Did) -> Result<uuid::Uuid>
306 where T: Serialize + Send {
307 self.send_message_by_hop(msg, destination, destination)
308 .await
309 }
310
311 async fn send_report_message<T>(&self, payload: &MessagePayload, msg: T) -> Result<()>
313 where T: Serialize + Send {
314 let relay = payload.relay.report(self.dht().did)?;
315
316 let transaction = Transaction::new(
317 relay.destination,
318 payload.transaction.tx_id,
319 msg,
320 self.session_sk(),
321 )?;
322
323 let pl = MessagePayload::new(transaction, self.session_sk(), relay)?;
324 self.send_payload(pl).await
325 }
326
327 async fn forward_by_relay(&self, payload: &MessagePayload, relay: MessageRelay) -> Result<()> {
330 let new_pl = MessagePayload::new(payload.transaction.clone(), self.session_sk(), relay)?;
331 self.send_payload(new_pl).await
332 }
333
334 async fn forward_payload(&self, payload: &MessagePayload, next_hop: Option<Did>) -> Result<()> {
336 let next_hop = self.infer_next_hop(payload.relay.destination, next_hop)?;
337 let relay = payload.relay.forward(self.dht().did, next_hop)?;
338 self.forward_by_relay(payload, relay).await
339 }
340
341 async fn reset_destination(&self, payload: &MessagePayload, next_hop: Did) -> Result<()> {
343 let relay = payload
344 .relay
345 .reset_destination(next_hop)
346 .forward(self.dht().did, next_hop)?;
347 self.forward_by_relay(payload, relay).await
348 }
349}
350
351#[cfg(test)]
352pub mod test {
353 use rand::Rng;
354
355 use super::*;
356 use crate::ecc::SecretKey;
357 use crate::message::Message;
358
359 #[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
360 pub struct TestData {
361 a: String,
362 b: i64,
363 c: f64,
364 d: bool,
365 }
366
367 pub fn new_test_payload(next_hop: Did) -> MessagePayload {
368 let test_data = TestData {
369 a: "hello".to_string(),
370 b: 111,
371 c: 2.33,
372 d: true,
373 };
374 new_payload(test_data, next_hop)
375 }
376
377 pub fn new_payload<T>(data: T, next_hop: Did) -> MessagePayload
378 where T: Serialize + DeserializeOwned {
379 let key = SecretKey::random();
380 let destination = SecretKey::random().address().into();
381 let session_sk = SessionSk::new_with_seckey(&key).unwrap();
382 MessagePayload::new_send(data, &session_sk, next_hop, destination).unwrap()
383 }
384
385 #[test]
386 fn new_then_verify() {
387 let key2 = SecretKey::random();
388 let did2 = key2.address().into();
389
390 let payload = new_test_payload(did2);
391 assert!(payload.verify());
392 }
393
394 #[test]
395 fn relay_destination_predicates_name_forwarding_state() -> Result<()> {
396 let local_key = SecretKey::random();
397 let session_sk = SessionSk::new_with_seckey(&local_key)?;
398 let local: Did = local_key.address().into();
399 let remote: Did = SecretKey::random().address().into();
400
401 let local_payload =
402 MessagePayload::new_send(Message::custom(b"local")?, &session_sk, local, local)?;
403 assert!(local_payload.is_relay_destination_for(local));
404 assert!(!local_payload.should_forward_from(local));
405
406 let remote_payload =
407 MessagePayload::new_send(Message::custom(b"remote")?, &session_sk, remote, remote)?;
408 assert!(!remote_payload.is_relay_destination_for(local));
409 assert!(remote_payload.should_forward_from(local));
410
411 Ok(())
412 }
413
414 #[test]
421 fn chunk_envelope_fits_reserve() {
422 use rings_transport::core::transport::TransportMessage;
423 use rings_transport::core::transport::MAX_DATA_CHANNEL_MESSAGE_SIZE;
424
425 use crate::chunk::ChunkList;
426 use crate::consts::MAX_CHUNK_ENVELOPE_OVERHEAD;
427 use crate::consts::TRANSPORT_CUSTOM_OVERHEAD;
428
429 let next_hop = SecretKey::random().address().into();
430 let chunk_size = MAX_DATA_CHANNEL_MESSAGE_SIZE
431 - (MAX_CHUNK_ENVELOPE_OVERHEAD + TRANSPORT_CUSTOM_OVERHEAD);
432 let data: Bytes = vec![0xab; chunk_size].into();
433 let chunk = ChunkList::split(&data, chunk_size)
434 .to_vec()
435 .pop()
436 .expect("one chunk");
437
438 let payload_bytes = new_payload(Message::Chunk(chunk), next_hop)
440 .to_bincode()
441 .unwrap();
442 let wire = bincode::serialize(&TransportMessage::Custom(payload_bytes.to_vec())).unwrap();
443
444 assert!(
445 wire.len() <= MAX_DATA_CHANNEL_MESSAGE_SIZE,
446 "wrapped chunk frame is {} bytes, exceeds limit {}; raise the reserves",
447 wire.len(),
448 MAX_DATA_CHANNEL_MESSAGE_SIZE,
449 );
450 }
451
452 #[test]
457 fn whole_message_boundary_fits_custom_wrapper() {
458 use rings_transport::core::transport::TransportMessage;
459 use rings_transport::core::transport::MAX_DATA_CHANNEL_MESSAGE_SIZE;
460
461 use crate::chunk::Framing;
462 use crate::chunk::WireReserves;
463
464 let reserves = WireReserves::PRODUCTION;
465 let limit = MAX_DATA_CHANNEL_MESSAGE_SIZE;
466 let payload_len = limit - reserves.whole;
468 assert_eq!(reserves.plan(payload_len, limit), Some(Framing::Whole));
469
470 let wire = bincode::serialize(&TransportMessage::Custom(vec![0u8; payload_len])).unwrap();
471 assert!(
472 wire.len() <= limit,
473 "whole wire {} exceeds limit {}",
474 wire.len(),
475 limit
476 );
477 assert!(matches!(
479 reserves.plan(payload_len + 1, limit),
480 Some(Framing::Chunked { .. })
481 ));
482 }
483
484 #[test]
485 fn test_message_payload_from_auto() {
486 let next_hop = SecretKey::random().address().into();
487
488 let payload = new_test_payload(next_hop);
489 let gzipped_encoded_payload = payload.encode().unwrap();
490 let payload2: MessagePayload = gzipped_encoded_payload.decode().unwrap();
491 assert_eq!(payload, payload2);
492
493 let gunzip_encoded_payload = payload.to_bincode().unwrap().encode().unwrap();
494 let payload2: MessagePayload = gunzip_encoded_payload.decode().unwrap();
495 assert_eq!(payload, payload2);
496 }
497
498 #[test]
499 fn test_message_payload_encode_len() {
500 let next_hop = SecretKey::random().address().into();
501 let data = rand::thread_rng().gen::<[u8; 32]>();
502
503 let data1 = data;
504 let msg1 = Message::custom(&data1).unwrap();
505 let payload1 = new_payload(msg1, next_hop);
506 let bytes1 = payload1.to_bincode().unwrap();
507 let encoded1 = payload1.encode().unwrap();
508 let encoded_bytes1: Vec<u8> = encoded1.into();
509
510 let data2 = data.repeat(2);
511 let msg2 = Message::custom(&data2).unwrap();
512 let payload2 = new_payload(msg2, next_hop);
513 let bytes2 = payload2.to_bincode().unwrap();
514 let encoded2 = payload2.encode().unwrap();
515 let encoded_bytes2: Vec<u8> = encoded2.into();
516
517 assert_eq!(bytes1.len() - data1.len(), bytes2.len() - data2.len());
518 assert_ne!(
519 encoded_bytes1.len() - data1.len(),
520 encoded_bytes2.len() - data2.len()
521 );
522 }
523}