1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright 2022 Parity Technologies (UK) Ltd.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

//! Mixnet configuration.

use super::{
	packet_queues::AuthoredPacketQueueConfig,
	sphinx::{KxSecret, MAX_HOPS},
};
use std::time::Duration;

/// Configuration that can vary between sessions depending on whether the local node is a mixnode
/// or not.
#[derive(Clone, Debug)]
pub struct SessionConfig {
	/// Authored packet queue configuration.
	pub authored_packet_queue: AuthoredPacketQueueConfig,
	/// Mean period between authored packet dispatches for the session. Cover packets are sent when
	/// there are no real packets to send, or when we randomly choose to send loop cover packets
	/// (see `Config::loop_cover_proportion`). This parameter, in combination with
	/// `Config::loop_cover_proportion`, bounds the rate at which messages can be sent. Note that
	/// this period is automatically increased during session transitions to keep the overall rate
	/// stable.
	pub mean_authored_packet_period: Duration,
}

/// Mixnet configuration.
#[derive(Clone, Debug)]
pub struct Config {
	/// The target for log messages.
	pub log_target: &'static str,

	/// The number of mixnodes to connect to when we are not a mixnode ourselves. When we are a
	/// mixnode, we connect to all other mixnodes.
	pub num_gateway_mixnodes: u32,

	/// The key-exchange secret key to use in session 0. This option is intended for testing
	/// purposes only.
	pub session_0_kx_secret: Option<KxSecret>,
	/// Used by sessions in which the local node is a mixnode. If this is not the same for all
	/// nodes, delay estimates may be off.
	pub mixnode_session: SessionConfig,
	/// Used by sessions in which the local node is not a mixnode. If [`None`], we will only
	/// participate in the mixnet during sessions in which we are a mixnode.
	pub non_mixnode_session: Option<SessionConfig>,

	/// Maximum number of packets waiting for their forwarding delay to elapse. When at the limit,
	/// any packets arriving that need forwarding will simply be dropped.
	pub forward_packet_queue_capacity: usize,
	/// Mean forwarding delay at each mixnode. This should really be the same for all nodes!
	pub mean_forwarding_delay: Duration,
	/// Conservative estimate of the network (and processing) delay per hop.
	pub per_hop_net_delay: Duration,

	/// Proportion of authored packets which should be loop cover packets (as opposed to drop cover
	/// packets or real packets). If this is not the same for all nodes, delay estimates may be
	/// off.
	pub loop_cover_proportion: f64,
	/// Generate cover packets? This option is intended for testing purposes only. It essentially
	/// just drops all cover packets instead of sending them.
	pub gen_cover_packets: bool,
	/// Number of hops for packets to traverse. Some packets may traverse more hops if necessary.
	/// Note this only affects packets whose headers are generated by this node. Must be <=
	/// [`MAX_HOPS`].
	pub num_hops: usize,

	/// Maximum number of outstanding SURBs to keep keys for. Must be greater than 0.
	pub surb_keystore_capacity: usize,
	/// Maximum number of incomplete messages to keep.
	pub max_incomplete_messages: usize,
	/// Maximum number of fragments to keep across all incomplete messages.
	pub max_incomplete_fragments: usize,
	/// Maximum number of fragments per message. This should really be the same for all nodes!
	pub max_fragments_per_message: usize,
}

impl Default for Config {
	fn default() -> Self {
		Self {
			log_target: "mixnet",

			num_gateway_mixnodes: 3,

			session_0_kx_secret: None,
			mixnode_session: SessionConfig {
				authored_packet_queue: AuthoredPacketQueueConfig {
					capacity: 50,
					multiple_messages: true,
				},
				mean_authored_packet_period: Duration::from_millis(100),
			},
			non_mixnode_session: Some(SessionConfig {
				authored_packet_queue: AuthoredPacketQueueConfig {
					capacity: 25,
					// By default only allow a single message to be queued in non-mixnode sessions.
					// Replies won't be sent in non-mixnode sessions, and requests really need to
					// be buffered externally anyway to handle eg retransmission. Limiting the
					// queue to a single message means we don't need to choose a session for
					// messages until the last moment (improving behaviour around session changes),
					// and minimises SPACE_IN_AUTHORED_PACKET_QUEUE events.
					multiple_messages: false,
				},
				mean_authored_packet_period: Duration::from_millis(1000),
			}),

			forward_packet_queue_capacity: 300,
			mean_forwarding_delay: Duration::from_secs(1),
			per_hop_net_delay: Duration::from_millis(300),

			loop_cover_proportion: 0.25,
			gen_cover_packets: true,
			num_hops: MAX_HOPS,

			surb_keystore_capacity: 200,
			max_incomplete_messages: 2000,
			max_incomplete_fragments: 2000,
			max_fragments_per_message: 25,
		}
	}
}