Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ path = "src/bin/saorsa-client/main.rs"

[dependencies]
# Core (provides EVERYTHING: networking, DHT, security, trust, storage)
saorsa-core = "0.11.1"
saorsa-core = "0.12.1"
saorsa-pqc = "0.4.0"

# Payment verification - autonomi network lookup + EVM payment
Expand Down
2 changes: 1 addition & 1 deletion src/ant_protocol/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ pub mod chunk;
pub use chunk::{
ChunkGetRequest, ChunkGetResponse, ChunkMessage, ChunkMessageBody, ChunkPutRequest,
ChunkPutResponse, ChunkQuoteRequest, ChunkQuoteResponse, ProtocolError, XorName,
CHUNK_PROTOCOL_ID, DATA_TYPE_CHUNK, MAX_CHUNK_SIZE, PROTOCOL_VERSION,
CHUNK_PROTOCOL_ID, DATA_TYPE_CHUNK, MAX_CHUNK_SIZE, MAX_WIRE_MESSAGE_SIZE, PROTOCOL_VERSION,
};
14 changes: 14 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,15 @@ pub struct NodeConfig {
#[serde(default)]
pub storage: StorageConfig,

/// Maximum application-layer message size in bytes.
///
/// Tunes the QUIC stream receive window and per-stream read buffer.
/// Default: [`MAX_WIRE_MESSAGE_SIZE`](crate::ant_protocol::MAX_WIRE_MESSAGE_SIZE)
/// (5 MiB — sufficient for 4 MiB data chunks plus serialization
/// envelope overhead).
#[serde(default = "default_max_message_size")]
pub max_message_size: usize,

/// Log level.
#[serde(default = "default_log_level")]
pub log_level: String,
Expand Down Expand Up @@ -248,6 +257,7 @@ impl Default for NodeConfig {
payment: PaymentConfig::default(),
bootstrap_cache: BootstrapCacheConfig::default(),
storage: StorageConfig::default(),
max_message_size: default_max_message_size(),
log_level: default_log_level(),
}
}
Expand Down Expand Up @@ -349,6 +359,10 @@ pub fn default_nodes_dir() -> PathBuf {
default_root_dir().join(NODES_SUBDIR)
}

fn default_max_message_size() -> usize {
crate::ant_protocol::MAX_WIRE_MESSAGE_SIZE
}

fn default_log_level() -> String {
"info".to_string()
}
Expand Down
3 changes: 3 additions & 0 deletions src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ impl NodeBuilder {
// Add bootstrap peers
core_config.bootstrap_peers.clone_from(&config.bootstrap);

// Forward max_message_size to the transport layer.
core_config.max_message_size = Some(config.max_message_size);

// Propagate network-mode tuning into saorsa-core where supported.
match config.network_mode {
NetworkMode::Production => {
Expand Down
27 changes: 17 additions & 10 deletions tests/e2e/data_types/chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,15 +212,16 @@ mod tests {
// Cross-Node Tests (require P2P network)
// =========================================================================

/// Test 8: One node asks another to store a chunk via P2P.
/// Test 8: One node asks another to store a max-size chunk (4 MiB) via P2P.
///
/// This test validates the full cross-node protocol flow:
/// This test validates the full cross-node protocol flow with the largest
/// allowed payload, exercising QUIC stream flow-control limits:
/// 1. Spins up a minimal 5-node local testnet
/// 2. A regular node (node 3) discovers connected peers
/// 3. Picks a random peer and sends a `ChunkPutRequest` to it
/// 3. Picks a random peer and sends a `ChunkPutRequest` with a 4 MiB chunk
/// 4. The target node stores the chunk and responds with success
/// 5. The regular node then sends a `ChunkGetRequest` to retrieve it
/// 6. Verifies the data round-trips correctly
/// 6. Verifies the 4 MiB data round-trips correctly
#[tokio::test(flavor = "multi_thread")]
async fn test_chunk_store_on_remote_node() {
let harness = TestHarness::setup_minimal()
Expand All @@ -240,13 +241,14 @@ mod tests {
let mut rng = rand::thread_rng();
let target_peer_id = peers.choose(&mut rng).expect("peers is non-empty");

// Use the max-size (4 MiB) chunk to exercise QUIC stream limits
let address = requester
.store_chunk_on_peer(target_peer_id, &fixture.small)
.store_chunk_on_peer(target_peer_id, &fixture.large)
.await
.expect("Failed to store chunk on remote node");
.expect("Failed to store max-size chunk on remote node");

// Verify the returned address matches the expected content hash
let expected_address = ChunkTestFixture::compute_address(&fixture.small);
let expected_address = ChunkTestFixture::compute_address(&fixture.large);
assert_eq!(
address, expected_address,
"Returned address should match computed content address"
Expand All @@ -256,12 +258,17 @@ mod tests {
let retrieved = requester
.get_chunk_from_peer(target_peer_id, &address)
.await
.expect("Failed to retrieve chunk from remote node");
.expect("Failed to retrieve max-size chunk from remote node");

let chunk = retrieved.expect("Chunk should exist on remote storage node");
let chunk = retrieved.expect("Max-size chunk should exist on remote storage node");
assert_eq!(
chunk.content.len(),
fixture.large.len(),
"Retrieved chunk size should match original (4 MiB)"
);
assert_eq!(
chunk.content.as_ref(),
fixture.small.as_slice(),
fixture.large.as_slice(),
"Retrieved data should match original"
);
assert_eq!(
Expand Down
3 changes: 3 additions & 0 deletions tests/e2e/testnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,9 @@ impl TestNetwork {
core_config
.bootstrap_peers
.clone_from(&node.bootstrap_addrs);
// Override the transport-layer message size to accommodate max-size
// chunks (4 MiB payload + serialization overhead = 5 MiB wire).
core_config.max_message_size = Some(saorsa_node::ant_protocol::MAX_WIRE_MESSAGE_SIZE);

// Create and start the P2P node
let p2p_node = P2PNode::new(core_config).await.map_err(|e| {
Expand Down
Loading