Skip to content

Commit de7a47d

Browse files
authored
feat: expose record count config (#786)
* expose record config * update default record counts * make fields optional * override record count in integration test
1 parent 3a57134 commit de7a47d

File tree

5 files changed

+155
-18
lines changed

5 files changed

+155
-18
lines changed

crates/common/src/config.rs

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ use std::error::Error;
77

88
// Default is 32 bytes to decrypt the TLS protocol messages.
99
const DEFAULT_MAX_RECV_ONLINE: usize = 32;
10+
// Default maximum number of TLS records to allow.
11+
//
12+
// This would allow for up to 50Mb upload from prover to verifier.
13+
const DEFAULT_RECORDS_LIMIT: usize = 256;
1014

1115
// Current version that is running.
1216
static VERSION: Lazy<Version> = Lazy::new(|| {
@@ -21,12 +25,18 @@ static VERSION: Lazy<Version> = Lazy::new(|| {
2125
pub struct ProtocolConfig {
2226
/// Maximum number of bytes that can be sent.
2327
max_sent_data: usize,
28+
/// Maximum number of application data records that can be sent.
29+
#[builder(setter(strip_option), default)]
30+
max_sent_records: Option<usize>,
2431
/// Maximum number of bytes that can be decrypted online, i.e. while the
2532
/// MPC-TLS connection is active.
2633
#[builder(default = "DEFAULT_MAX_RECV_ONLINE")]
2734
max_recv_data_online: usize,
2835
/// Maximum number of bytes that can be received.
2936
max_recv_data: usize,
37+
/// Maximum number of application data records that can be received.
38+
#[builder(setter(strip_option), default)]
39+
max_recv_records: Option<usize>,
3040
/// Version that is being run by prover/verifier.
3141
#[builder(setter(skip), default = "VERSION.clone()")]
3242
version: Version,
@@ -54,6 +64,12 @@ impl ProtocolConfig {
5464
self.max_sent_data
5565
}
5666

67+
/// Returns the maximum number of application data records that can
68+
/// be sent.
69+
pub fn max_sent_records(&self) -> Option<usize> {
70+
self.max_sent_records
71+
}
72+
5773
/// Returns the maximum number of bytes that can be decrypted online.
5874
pub fn max_recv_data_online(&self) -> usize {
5975
self.max_recv_data_online
@@ -63,6 +79,12 @@ impl ProtocolConfig {
6379
pub fn max_recv_data(&self) -> usize {
6480
self.max_recv_data
6581
}
82+
83+
/// Returns the maximum number of application data records that can
84+
/// be received.
85+
pub fn max_recv_records(&self) -> Option<usize> {
86+
self.max_recv_records
87+
}
6688
}
6789

6890
/// Protocol configuration validator used by checker (i.e. verifier) to perform
@@ -71,8 +93,14 @@ impl ProtocolConfig {
7193
pub struct ProtocolConfigValidator {
7294
/// Maximum number of bytes that can be sent.
7395
max_sent_data: usize,
96+
/// Maximum number of application data records that can be sent.
97+
#[builder(default = "DEFAULT_RECORDS_LIMIT")]
98+
max_sent_records: usize,
7499
/// Maximum number of bytes that can be received.
75100
max_recv_data: usize,
101+
/// Maximum number of application data records that can be received.
102+
#[builder(default = "DEFAULT_RECORDS_LIMIT")]
103+
max_recv_records: usize,
76104
/// Version that is being run by checker.
77105
#[builder(setter(skip), default = "VERSION.clone()")]
78106
version: Version,
@@ -89,15 +117,28 @@ impl ProtocolConfigValidator {
89117
self.max_sent_data
90118
}
91119

120+
/// Returns the maximum number of application data records that can
121+
/// be sent.
122+
pub fn max_sent_records(&self) -> usize {
123+
self.max_sent_records
124+
}
125+
92126
/// Returns the maximum number of bytes that can be received.
93127
pub fn max_recv_data(&self) -> usize {
94128
self.max_recv_data
95129
}
96130

131+
/// Returns the maximum number of application data records that can
132+
/// be received.
133+
pub fn max_recv_records(&self) -> usize {
134+
self.max_recv_records
135+
}
136+
97137
/// Performs compatibility check of the protocol configuration between
98138
/// prover and verifier.
99139
pub fn validate(&self, config: &ProtocolConfig) -> Result<(), ProtocolConfigError> {
100140
self.check_max_transcript_size(config.max_sent_data, config.max_recv_data)?;
141+
self.check_max_records(config.max_sent_records, config.max_recv_records)?;
101142
self.check_version(&config.version)?;
102143
Ok(())
103144
}
@@ -125,6 +166,32 @@ impl ProtocolConfigValidator {
125166
Ok(())
126167
}
127168

169+
fn check_max_records(
170+
&self,
171+
max_sent_records: Option<usize>,
172+
max_recv_records: Option<usize>,
173+
) -> Result<(), ProtocolConfigError> {
174+
if let Some(max_sent_records) = max_sent_records {
175+
if max_sent_records > self.max_sent_records {
176+
return Err(ProtocolConfigError::max_record_count(format!(
177+
"max_sent_records {} is greater than the configured limit {}",
178+
max_sent_records, self.max_sent_records,
179+
)));
180+
}
181+
}
182+
183+
if let Some(max_recv_records) = max_recv_records {
184+
if max_recv_records > self.max_recv_records {
185+
return Err(ProtocolConfigError::max_record_count(format!(
186+
"max_recv_records {} is greater than the configured limit {}",
187+
max_recv_records, self.max_recv_records,
188+
)));
189+
}
190+
}
191+
192+
Ok(())
193+
}
194+
128195
// Checks if both versions are the same (might support check for different but
129196
// compatible versions in the future).
130197
fn check_version(&self, peer_version: &Version) -> Result<(), ProtocolConfigError> {
@@ -165,6 +232,13 @@ impl ProtocolConfigError {
165232
}
166233
}
167234

235+
fn max_record_count(msg: impl Into<String>) -> Self {
236+
Self {
237+
kind: ErrorKind::MaxRecordCount,
238+
source: Some(msg.into().into()),
239+
}
240+
}
241+
168242
fn version(msg: impl Into<String>) -> Self {
169243
Self {
170244
kind: ErrorKind::Version,
@@ -176,7 +250,8 @@ impl ProtocolConfigError {
176250
impl fmt::Display for ProtocolConfigError {
177251
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178252
match self.kind {
179-
ErrorKind::MaxTranscriptSize => write!(f, "max transcript size error")?,
253+
ErrorKind::MaxTranscriptSize => write!(f, "max transcript size exceeded")?,
254+
ErrorKind::MaxRecordCount => write!(f, "max record count exceeded")?,
180255
ErrorKind::Version => write!(f, "version error")?,
181256
}
182257

@@ -191,6 +266,7 @@ impl fmt::Display for ProtocolConfigError {
191266
#[derive(Debug)]
192267
enum ErrorKind {
193268
MaxTranscriptSize,
269+
MaxRecordCount,
194270
Version,
195271
}
196272

crates/mpc-tls/src/config.rs

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,34 @@
11
use derive_builder::Builder;
22

3-
const MIN_SENT: usize = 32;
4-
const MIN_SENT_RECORDS: usize = 8;
5-
const MIN_RECV: usize = 32;
6-
const MIN_RECV_RECORDS: usize = 8;
3+
/// Number of TLS protocol bytes that will be sent.
4+
const PROTOCOL_DATA_SENT: usize = 32;
5+
/// Number of TLS protocol bytes that will be received.
6+
const PROTOCOL_DATA_RECV: usize = 32;
7+
8+
/// Number of TLS protocol records that we need to allocate in addition
9+
/// to the application data records.
10+
const PROTOCOL_RECORD_COUNT_SENT: usize = 2;
11+
/// Number of TLS protocol records that we need to allocate in addition
12+
/// to the application data records.
13+
const PROTOCOL_RECORD_COUNT_RECV: usize = 2;
14+
15+
/// Computes the record count configuration given the data volume.
16+
///
17+
/// Accurately estimating a good default is challenging as we do not
18+
/// know exactly how much data will be packed into each record in advance.
19+
fn default_record_count(max_data: usize) -> usize {
20+
// We assume a minimum of 8 records for the first 4KB.
21+
const MIN: usize = 8;
22+
23+
// Then we estimate that after 4KB of data is transmitted that they will
24+
// average 4KB in size.
25+
let remainder = max_data.saturating_sub(4096);
26+
let count = remainder.div_ceil(4096);
27+
28+
// For example, if max_data=32KB then this will return 15. That will result
29+
// in about 3MB upload from prover to verifier.
30+
MIN + count
31+
}
732

833
/// MPC-TLS configuration.
934
#[derive(Debug, Clone, Builder)]
@@ -43,7 +68,7 @@ impl ConfigBuilder {
4368
/// Builds the configuration.
4469
pub fn build(&self) -> Result<Config, ConfigBuilderError> {
4570
let defer_decryption = self.defer_decryption.unwrap_or(true);
46-
let max_sent = MIN_SENT
71+
let max_sent = PROTOCOL_DATA_SENT
4772
+ self
4873
.max_sent
4974
.ok_or(ConfigBuilderError::UninitializedField("max_sent"))?;
@@ -60,15 +85,15 @@ impl ConfigBuilder {
6085
));
6186
}
6287

63-
max_recv_online += MIN_RECV;
64-
max_recv += MIN_RECV;
88+
max_recv_online += PROTOCOL_DATA_RECV;
89+
max_recv += PROTOCOL_DATA_RECV;
6590

6691
let max_sent_records = self
6792
.max_sent_records
68-
.unwrap_or_else(|| MIN_SENT_RECORDS + max_sent.div_ceil(16384));
93+
.unwrap_or_else(|| PROTOCOL_RECORD_COUNT_SENT + default_record_count(max_sent));
6994
let max_recv_records = self
7095
.max_recv_records
71-
.unwrap_or_else(|| MIN_RECV_RECORDS + max_recv.div_ceil(16384));
96+
.unwrap_or_else(|| PROTOCOL_RECORD_COUNT_RECV + default_record_count(max_recv));
7297

7398
Ok(Config {
7499
defer_decryption,
@@ -80,3 +105,13 @@ impl ConfigBuilder {
80105
})
81106
}
82107
}
108+
109+
#[cfg(test)]
110+
mod tests {
111+
use super::*;
112+
113+
#[test]
114+
fn test_default_record_count() {
115+
assert_eq!(default_record_count(1 << 15), 15);
116+
}
117+
}

crates/prover/src/config.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,22 @@ impl ProverConfig {
4949
}
5050

5151
pub(crate) fn build_mpc_tls_config(&self) -> Config {
52-
Config::builder()
52+
let mut builder = Config::builder();
53+
54+
builder
5355
.defer_decryption(self.defer_decryption_from_start)
5456
.max_sent(self.protocol_config.max_sent_data())
5557
.max_recv_online(self.protocol_config.max_recv_data_online())
56-
.max_recv(self.protocol_config.max_recv_data())
57-
.build()
58-
.unwrap()
58+
.max_recv(self.protocol_config.max_recv_data());
59+
60+
if let Some(max_sent_records) = self.protocol_config.max_sent_records() {
61+
builder.max_sent_records(max_sent_records);
62+
}
63+
64+
if let Some(max_recv_records) = self.protocol_config.max_recv_records() {
65+
builder.max_recv_records(max_recv_records);
66+
}
67+
68+
builder.build().unwrap()
5969
}
6070
}

crates/tests-integration/tests/defer_decryption.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@ use tracing::instrument;
1616

1717
// Maximum number of bytes that can be sent from prover to server
1818
const MAX_SENT_DATA: usize = 1 << 12;
19+
// Maximum number of application records sent from prover to server
20+
const MAX_SENT_RECORDS: usize = 4;
1921
// Maximum number of bytes that can be received by prover from server
2022
const MAX_RECV_DATA: usize = 1 << 14;
23+
// Maximum number of application records received by prover from server
24+
const MAX_RECV_RECORDS: usize = 6;
2125

2226
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
2327
#[ignore]
@@ -51,7 +55,9 @@ async fn prover<T: AsyncWrite + AsyncRead + Send + Unpin + 'static>(notary_socke
5155
.protocol_config(
5256
ProtocolConfig::builder()
5357
.max_sent_data(MAX_SENT_DATA)
58+
.max_sent_records(MAX_SENT_RECORDS)
5459
.max_recv_data(MAX_RECV_DATA)
60+
.max_recv_records(MAX_RECV_RECORDS)
5561
.build()
5662
.unwrap(),
5763
)

crates/verifier/src/config.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,21 @@ impl VerifierConfig {
4343
}
4444

4545
pub(crate) fn build_mpc_tls_config(&self, protocol_config: &ProtocolConfig) -> Config {
46-
Config::builder()
46+
let mut builder = Config::builder();
47+
48+
builder
4749
.max_sent(protocol_config.max_sent_data())
4850
.max_recv_online(protocol_config.max_recv_data_online())
49-
.max_recv(protocol_config.max_recv_data())
50-
.build()
51-
.unwrap()
51+
.max_recv(protocol_config.max_recv_data());
52+
53+
if let Some(max_sent_records) = protocol_config.max_sent_records() {
54+
builder.max_sent_records(max_sent_records);
55+
}
56+
57+
if let Some(max_recv_records) = protocol_config.max_recv_records() {
58+
builder.max_recv_records(max_recv_records);
59+
}
60+
61+
builder.build().unwrap()
5262
}
5363
}

0 commit comments

Comments
 (0)