Skip to content

Commit de740e1

Browse files
AndreiEresgithub-actions[bot]bkchr
authored
Limit the size of the statement for further gossiping (#9965)
# Description Limits the size of statements that are further gossiped over the network to prevent skipping oversized messages. The limit is set to match the network protocol's max statement notification size (1 MB), accounting for 1-byte vector length overhead because statements are sent as `Vec<Statement>`. ## Integration Affected crates: - `sc-statement-store`: Now depends on `sc-network-statement` for size constants - `sc-network-statement`: `MAX_STATEMENT_NOTIFICATION_SIZE` is now public For downstream users: - Statements larger than 1 MB will now be rejected earlier before the validation pipeline --------- Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Bastian Köcher <[email protected]>
1 parent 2689733 commit de740e1

File tree

5 files changed

+51
-1
lines changed

5 files changed

+51
-1
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

prdoc/pr_9965.prdoc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
title: Limit the size of the statement for further gossiping
2+
doc:
3+
- audience: Node Dev
4+
description: "Limits the size of statements that are further gossiped over the network to prevent skipping oversized messages. The limit is set to match the network protocol's `MAX_STATEMENT_NOTIFICATION_SIZE` (1 MB), accounting for 1-byte vector length overhead because statements are sent as `Vec<Statement>`."
5+
crates:
6+
- name: sc-network-statement
7+
bump: minor
8+
- name: sc-statement-store
9+
bump: minor

substrate/client/network/statement/src/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub(crate) const PROPAGATE_TIMEOUT: time::Duration = time::Duration::from_millis
2727
pub(crate) const MAX_KNOWN_STATEMENTS: usize = 4 * 1024 * 1024; // * 32 bytes for hash = 128 MB per peer
2828

2929
/// Maximum allowed size for a statement notification.
30-
pub(crate) const MAX_STATEMENT_NOTIFICATION_SIZE: u64 = 1024 * 1024;
30+
pub const MAX_STATEMENT_NOTIFICATION_SIZE: u64 = 1024 * 1024;
3131

3232
/// Maximum number of statement validation request we keep at any moment.
3333
pub(crate) const MAX_PENDING_STATEMENTS: usize = 2 * 1024 * 1024;

substrate/client/statement-store/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ parking_lot = { workspace = true, default-features = true }
2222
prometheus-endpoint = { workspace = true, default-features = true }
2323
sc-client-api = { workspace = true, default-features = true }
2424
sc-keystore = { workspace = true, default-features = true }
25+
sc-network-statement = { workspace = true, default-features = true }
2526
sp-api = { workspace = true, default-features = true }
2627
sp-blockchain = { workspace = true, default-features = true }
2728
sp-core = { workspace = true, default-features = true }

substrate/client/statement-store/src/lib.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ pub const DEFAULT_MAX_TOTAL_STATEMENTS: usize = 4 * 1024 * 1024; // ~4 million
8383
/// The maximum amount of data the statement store can hold, regardless of the number of
8484
/// statements from which the data originates.
8585
pub const DEFAULT_MAX_TOTAL_SIZE: usize = 2 * 1024 * 1024 * 1024; // 2GiB
86+
/// The maximum size of a single statement in bytes.
87+
/// Accounts for the 1-byte vector length prefix when statements are gossiped as `Vec<Statement>`.
88+
pub const MAX_STATEMENT_SIZE: usize =
89+
sc_network_statement::config::MAX_STATEMENT_NOTIFICATION_SIZE as usize - 1;
8690

8791
const MAINTENANCE_PERIOD: std::time::Duration = std::time::Duration::from_secs(30);
8892

@@ -890,6 +894,18 @@ impl StatementStore for Store {
890894
/// Submit a statement to the store. Validates the statement and returns validation result.
891895
fn submit(&self, statement: Statement, source: StatementSource) -> SubmitResult {
892896
let hash = statement.hash();
897+
let encoded_size = statement.encoded_size();
898+
if encoded_size > MAX_STATEMENT_SIZE {
899+
log::debug!(
900+
target: LOG_TARGET,
901+
"Statement is too big for propogation: {:?} ({}/{} bytes)",
902+
HexDisplay::from(&hash),
903+
statement.encoded_size(),
904+
MAX_STATEMENT_SIZE
905+
);
906+
return SubmitResult::Ignored
907+
}
908+
893909
match self.index.read().query(&hash) {
894910
IndexQuery::Expired =>
895911
if !source.can_be_resubmitted() {
@@ -1079,6 +1095,7 @@ mod tests {
10791095
Some(a) if a == account(2) => (2, 1000),
10801096
Some(a) if a == account(3) => (3, 1000),
10811097
Some(a) if a == account(4) => (4, 1000),
1098+
Some(a) if a == account(42) => (42, 42 * crate::MAX_STATEMENT_SIZE as u32),
10821099
_ => (2, 2000),
10831100
};
10841101
Ok(ValidStatement{ max_count, max_size })
@@ -1385,6 +1402,28 @@ mod tests {
13851402
assert_eq!(expected_statements, statements);
13861403
}
13871404

1405+
#[test]
1406+
fn max_statement_size_for_gossiping() {
1407+
let (store, _temp) = test_store();
1408+
store.index.write().options.max_total_size = 42 * crate::MAX_STATEMENT_SIZE;
1409+
1410+
assert_eq!(
1411+
store.submit(
1412+
statement(42, 1, Some(1), crate::MAX_STATEMENT_SIZE - 500),
1413+
StatementSource::Local
1414+
),
1415+
SubmitResult::New(NetworkPriority::High)
1416+
);
1417+
1418+
assert_eq!(
1419+
store.submit(
1420+
statement(42, 2, Some(1), 2 * crate::MAX_STATEMENT_SIZE),
1421+
StatementSource::Local
1422+
),
1423+
SubmitResult::Ignored
1424+
);
1425+
}
1426+
13881427
#[test]
13891428
fn expired_statements_are_purged() {
13901429
use super::DEFAULT_PURGE_AFTER_SEC;

0 commit comments

Comments
 (0)