sphinx_packet/packet/
builder.rs

1use crate::version::Version;
2use crate::{
3    header::{delays::Delay, SphinxHeader},
4    payload::Payload,
5    route::{Destination, Node},
6    Result, SphinxPacket,
7};
8use x25519_dalek::StaticSecret;
9
10pub const DEFAULT_PAYLOAD_SIZE: usize = 1024;
11
12pub struct SphinxPacketBuilder<'a> {
13    payload_size: usize,
14    initial_secret: Option<&'a StaticSecret>,
15    version: Version,
16}
17
18impl<'a> SphinxPacketBuilder<'a> {
19    pub fn new() -> Self {
20        Self::default()
21    }
22
23    #[must_use]
24    pub fn with_version(mut self, version: Version) -> Self {
25        self.version = version;
26        self
27    }
28
29    #[must_use]
30    pub fn with_payload_size(mut self, payload_size: usize) -> Self {
31        self.payload_size = payload_size;
32        self
33    }
34
35    #[must_use]
36    pub fn with_initial_secret(mut self, initial_secret: &'a StaticSecret) -> Self {
37        self.initial_secret = Some(initial_secret);
38        self
39    }
40
41    pub fn build_packet<M: AsRef<[u8]>>(
42        &self,
43        message: M,
44        route: &[Node],
45        destination: &Destination,
46        delays: &[Delay],
47    ) -> Result<SphinxPacket> {
48        let initial_secret = match self.initial_secret.as_ref() {
49            Some(initial_secret) => initial_secret,
50            None => &StaticSecret::random(),
51        };
52
53        let built_header =
54            SphinxHeader::new_versioned(initial_secret, route, delays, destination, self.version);
55
56        let payload_keys = built_header.derive_payload_keys();
57        let header = built_header.into_header();
58
59        // no need to check if plaintext has correct length as this check is already performed in payload encapsulation
60        let payload =
61            Payload::encapsulate_message(message.as_ref(), &payload_keys, self.payload_size)?;
62        Ok(SphinxPacket { header, payload })
63    }
64}
65
66impl Default for SphinxPacketBuilder<'_> {
67    fn default() -> Self {
68        SphinxPacketBuilder {
69            payload_size: DEFAULT_PAYLOAD_SIZE,
70            initial_secret: None,
71            version: Default::default(),
72        }
73    }
74}