Skip to content

feat(network)!: regulate GetBlocks with paired streams - #892

Draft
czarcas7ic wants to merge 79 commits into
mainfrom
adam/getblocks-regulation-v2
Draft

feat(network)!: regulate GetBlocks with paired streams#892
czarcas7ic wants to merge 79 commits into
mainfrom
adam/getblocks-regulation-v2

Conversation

@czarcas7ic

@czarcas7ic czarcas7ic commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Motivation

This draft is retained as the reference for the replacement stack: #942 (owned storage), #943 (generic paired transport), #944 (outgoing request ownership), and #945 (serving activation). The initial stack preserved this PR at 953b85b18; #941 was later closed and its backport removed from the replacement drafts in favor of the separate Iroh upgrade in #935. This reference still records the original backport-based implementation. See the audit map.

Solution

Use paired native block-sync streams and sequential serving, with one response slot per authenticated identity and 64 per node. Retain capacity through storage, results, encodes, and writes across cancellation and reconnects. Settle outgoing requests across publication, expiry, reset, and writer startup. Preserve cooldowns for unanswered remote resets and defer session-capacity races without closing healthy connections. The previous native layout is replaced while other services and legacy fallback remain available. Property coverage remains separate in #896.

Testing

The latest two fixes pass 29 targeted regressions and network Clippy. Before withdrawing the backport, the identical completed stack passed 405 focused tests, 22 cluster integration tests without retries, and workspace all-target Clippy, formatting, Markdown lint, and changelog checks. Those results do not validate the replacement stack with the separate Iroh upgrade; activation needs that integration check.

Earlier long transport results and their limitations remain in the validation evidence. Those long gates were not rerun. The earlier full workspace run had three unavailable loopback source addresses and two legacy mainnet-sync timeouts; it was not repeated for this split.

Changelog

The combined fragment remains here; each replacement draft has its own fragment. Used Codex for implementation, tests, and documentation.

@chatgpt-codex-connector

This comment was marked as resolved.

@zakura-core zakura-core deleted a comment from chatgpt-codex-connector Bot Sep 4, 2026
Base automatically changed from adam/p2p-regulation-mechanics-v2 to main September 4, 2026 22:09
@czarcas7ic
czarcas7ic force-pushed the adam/getblocks-regulation-v2 branch from b24ab05 to 85401ce Compare September 4, 2026 22:14
@czarcas7ic
czarcas7ic marked this pull request as ready for review September 5, 2026 01:20
chatgpt-codex-connector[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

@evan-forbes

Copy link
Copy Markdown
Contributor

one thing we have to think about when merging to main is that if we cut a releases imbetween work here we'll have to update the blocksync / headersync / discovery versions a few times which is cumbersome

@evan-forbes evan-forbes left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!

/// charges until the underlying state work finishes.
#[serde(with = "humantime_serde")]
pub query_timeout: Duration,
}

@evan-forbes evan-forbes Sep 6, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one of the ideas in 747 was to reuse a lot of these logic instead of making one per message

not sure if we can do this for everything but many of these seem like they could be generalized

I'm biased, and not sure how feasible it is irl, but the idea of defining the message then adding and configuring the functions then and there seems nice

@czarcas7ic czarcas7ic Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now reduced to the following config:

pub struct GetBlocksRegulationConfig {
    pub node_active_requests: usize,
    pub query_timeout: Duration,
}

Because we might want these to differ per message.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left this unresolved because I could easily be convinced that maybe we just keep these global as well.

Comment thread crates/zakura-network/src/zakura/block_sync/config.rs Outdated
Comment thread crates/zakura-network/src/zakura/block_sync/peer_routine.rs Outdated
@czarcas7ic czarcas7ic changed the title feat(network)!: regulate GetBlocks serving work feat(network)!: regulate GetBlocks with paired streams Sep 9, 2026
@czarcas7ic
czarcas7ic marked this pull request as draft September 9, 2026 05:26

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 11beaec168

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +4752 to +4754
timeout(write_timeout, send.write_all(&frame))
.await
.map_err(|_| -> BoxError { "Zakura outbound frame write timed out".into() })??;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep paired data-write timeouts stream-local

When the block-sync data stream remains flow-controlled for 32 seconds—for example, because its receiver is paused while header-sync or gossip siblings are still healthy—this timeout becomes a generic write error. persistent_stream_worker_with_policy handles that error by calling context.connection_token.cancel() at lines 4301-4310, so the entire QUIC connection and every unrelated service stream are dropped instead of only retiring and reopening the paired block-sync session. Classify paired data timeouts separately and reset/cancel only the pair.

Useful? React with 👍 / 👎.

@czarcas7ic
czarcas7ic changed the base branch from adam/quic-loss-recovery-backport to main September 9, 2026 05:43
});
}

pub(super) fn trace_queue_send_failed(&self, msg: &BlockSyncMessage, error: &OrderedSendError) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before we would reserve download resources, then try to queue the request, then if failed we would emit this and release the resources. Now, we reserve a queue slot first here

let slot = match request_sender.try_reserve_guarded() {

and if the queue is full, we stop before taking work or reserving download resources.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants