diff --git a/zebra-network/src/zakura/block_sync/admission.rs b/zebra-network/src/zakura/block_sync/admission.rs index ec8ae6b5ae3..b8e4d2032d9 100644 --- a/zebra-network/src/zakura/block_sync/admission.rs +++ b/zebra-network/src/zakura/block_sync/admission.rs @@ -30,8 +30,8 @@ pub(super) struct AdmissionDecision { pub(super) max_request_bytes: u64, } -// Return the highest height that can be rescued by a floor-rescue request. -pub(super) fn max_floor_rescue_start_height(download_floor: block::Height) -> block::Height { +/// Return the highest start height that can be rescued by a floor request. +pub(super) fn floor_rescue_high(download_floor: block::Height) -> block::Height { next_height(download_floor).unwrap_or(download_floor) } @@ -39,8 +39,8 @@ pub(super) fn request_priority( download_floor: block::Height, start_height: block::Height, ) -> RequestPriority { - // This is <= because down - if start_height <= max_floor_rescue_start_height(download_floor) { + // The next height above the floor can still unblock the current floor. + if start_height <= floor_rescue_high(download_floor) { RequestPriority::Floor } else { RequestPriority::AboveFloor diff --git a/zebra-network/src/zakura/block_sync/config.rs b/zebra-network/src/zakura/block_sync/config.rs index d9225a2c643..92674d11f4c 100644 --- a/zebra-network/src/zakura/block_sync/config.rs +++ b/zebra-network/src/zakura/block_sync/config.rs @@ -31,7 +31,7 @@ pub const MAX_BS_INFLIGHT_REQUESTS: u32 = 32_768; /// Default total response byte target advertised per range response. pub const DEFAULT_BS_MAX_RESPONSE_BYTES: u32 = 32 * 1024 * 1024; /// Default global byte budget reserved for later block-download scheduling. -pub const DEFAULT_BS_MAX_INFLIGHT_BLOCK_BYTES: u64 = 2 * 1024 * 1024 * 1024; +pub const DEFAULT_BS_MAX_INFLIGHT_BLOCK_BYTES: u64 = 6 * 1024 * 1024 * 1024; /// Worst-case serialized bytes reserved per requested block body. /// /// Block-sync reserves this much per requested block at send time and only ever diff --git a/zebra-network/src/zakura/block_sync/peer_routine.rs b/zebra-network/src/zakura/block_sync/peer_routine.rs index 5c51ad0343f..f4ec415eec7 100644 --- a/zebra-network/src/zakura/block_sync/peer_routine.rs +++ b/zebra-network/src/zakura/block_sync/peer_routine.rs @@ -31,9 +31,7 @@ use tokio_util::sync::CancellationToken; use super::events::RoutineToReactor; use super::{ - admission::{ - admission_decision, max_floor_rescue_start_height, AdmissionSnapshot, RequestPriority, - }, + admission::{admission_decision, floor_rescue_high, AdmissionSnapshot, RequestPriority}, peer_registry::{hard_outbound_capacity, PeerRegistry}, pipe::block_sync_guard, reactor::{ @@ -570,11 +568,11 @@ impl PeerRoutine { let max_count = local_peer_count_cap; let response_byte_cap = u64::from(self.max_response_bytes.max(1)); - let sequencer_view = *self.sequencer_view.borrow(); - let floor_high = max_floor_rescue_start_height(sequencer_view.download_floor); + let view = *self.sequencer_view.borrow(); + let floor_high = floor_rescue_high(view.download_floor); let mut request_priority = RequestPriority::Floor; let (reserved_above_floor_bytes, reserved_above_floor_blocks) = - self.work.reserved_above(sequencer_view.download_floor); + self.work.reserved_above(view.download_floor); let mut items = if servable_low <= floor_high && self .work @@ -589,11 +587,11 @@ impl PeerRoutine { admission_decision( &self.config, AdmissionSnapshot { - download_floor: sequencer_view.download_floor, - reorder_buffered_bytes: sequencer_view.reorder_buffered_bytes, - reorder_buffered_blocks: sequencer_view.reorder_len, - applying_buffered_bytes: sequencer_view.applying_buffered_bytes, - applying_buffered_blocks: sequencer_view.applying_len, + download_floor: view.download_floor, + reorder_buffered_bytes: view.reorder_buffered_bytes, + reorder_buffered_blocks: view.reorder_len, + applying_buffered_bytes: view.applying_buffered_bytes, + applying_buffered_blocks: view.applying_len, sequencer_input_queued_bytes: self .sequencer_input_bytes .load(std::sync::atomic::Ordering::Relaxed), @@ -629,11 +627,11 @@ impl PeerRoutine { let Some(decision) = admission_decision( &self.config, AdmissionSnapshot { - download_floor: sequencer_view.download_floor, - reorder_buffered_bytes: sequencer_view.reorder_buffered_bytes, - reorder_buffered_blocks: sequencer_view.reorder_len, - applying_buffered_bytes: sequencer_view.applying_buffered_bytes, - applying_buffered_blocks: sequencer_view.applying_len, + download_floor: view.download_floor, + reorder_buffered_bytes: view.reorder_buffered_bytes, + reorder_buffered_blocks: view.reorder_len, + applying_buffered_bytes: view.applying_buffered_bytes, + applying_buffered_blocks: view.applying_len, sequencer_input_queued_bytes: self .sequencer_input_bytes .load(std::sync::atomic::Ordering::Relaxed), @@ -1188,17 +1186,17 @@ impl PeerRoutine { self.record_received(serialized_bytes); self.trace_body_received(height, serialized_bytes, None, None, None); - let view = *self.sequencer_view.borrow(); + let sequencer_view = *self.sequencer_view.borrow(); let (reserved_above_floor_bytes, reserved_above_floor_blocks) = - self.work.reserved_above(view.download_floor); + self.work.reserved_above(sequencer_view.download_floor); let Some(decision) = admission_decision( &self.config, AdmissionSnapshot { - download_floor: view.download_floor, - reorder_buffered_bytes: view.reorder_buffered_bytes, - reorder_buffered_blocks: view.reorder_len, - applying_buffered_bytes: view.applying_buffered_bytes, - applying_buffered_blocks: view.applying_len, + download_floor: sequencer_view.download_floor, + reorder_buffered_bytes: sequencer_view.reorder_buffered_bytes, + reorder_buffered_blocks: sequencer_view.reorder_len, + applying_buffered_bytes: sequencer_view.applying_buffered_bytes, + applying_buffered_blocks: sequencer_view.applying_len, sequencer_input_queued_bytes: self .sequencer_input_bytes .load(std::sync::atomic::Ordering::Relaxed), diff --git a/zebra-network/src/zakura/block_sync/reorder.rs b/zebra-network/src/zakura/block_sync/reorder.rs index 06bccc8622a..33ff6b73ac8 100644 --- a/zebra-network/src/zakura/block_sync/reorder.rs +++ b/zebra-network/src/zakura/block_sync/reorder.rs @@ -23,7 +23,7 @@ impl ReorderBuffer { } /// Highest buffered height, if any. The shed-for-floor-starvation path drops - /// this (the body furthest from the download floor) to free budget for a + /// this (the body furthest from the committed floor) to free budget for a /// lower, commit-unblocking request. pub(super) fn max_height(&self) -> Option { self.blocks.keys().next_back().copied() diff --git a/zebra-network/src/zakura/block_sync/sequencer_task.rs b/zebra-network/src/zakura/block_sync/sequencer_task.rs index bd0bad192f6..473a6655f59 100644 --- a/zebra-network/src/zakura/block_sync/sequencer_task.rs +++ b/zebra-network/src/zakura/block_sync/sequencer_task.rs @@ -134,12 +134,6 @@ pub(super) enum SequencerControlInput { /// the peer-outstanding clause of `reset_tip_conflicts_with_local_work`. peer_outstanding_conflicts_at_tip: bool, }, - /// Synchronously pop the speculative high tail until a floor request can - /// reserve `needed_bytes`, then wake the requester to retry the reservation. - FundFloorReservation { - needed_bytes: u64, - reply: oneshot::Sender, - }, /// A verifier apply completion. ApplyFinished { token: BlockApplyToken, @@ -148,6 +142,12 @@ pub(super) enum SequencerControlInput { result: BlockApplyResult, local_frontier: Option, }, + /// Synchronously pop the speculative high tail until a floor request can + /// reserve `needed_bytes`, then wake the requester to retry the reservation. + FundFloorReservation { + needed_bytes: u64, + reply: oneshot::Sender, + }, } /// The progress view the reactor reacts to. A `watch` (latest-wins) send never @@ -349,6 +349,16 @@ impl SequencerTask { .await; true } + SequencerControlInput::ApplyFinished { + token, + height, + hash, + result, + local_frontier, + } => { + self.handle_apply_finished(token, height, hash, result, local_frontier) + .await + } SequencerControlInput::FundFloorReservation { needed_bytes, reply, @@ -362,16 +372,6 @@ impl SequencerTask { let _ = reply.send(self.budget.available() >= needed_bytes); shed } - SequencerControlInput::ApplyFinished { - token, - height, - hash, - result, - local_frontier, - } => { - self.handle_apply_finished(token, height, hash, result, local_frontier) - .await - } } } diff --git a/zebra-network/src/zakura/handler.rs b/zebra-network/src/zakura/handler.rs index 5e4b000cb4c..acb10793499 100644 --- a/zebra-network/src/zakura/handler.rs +++ b/zebra-network/src/zakura/handler.rs @@ -67,12 +67,12 @@ use crate::{ }; use crate::{BoxError, Config, MAX_TX_INV_IN_SENT_MESSAGE}; -/// Conservative default for total Zakura connections when P2P v2 is enabled. -pub const DEFAULT_ZAKURA_MAX_CONNECTIONS: usize = 32; -/// Conservative default for simultaneous Zakura control handshakes. -pub const DEFAULT_ZAKURA_MAX_PENDING_HANDSHAKES: usize = 8; -/// Conservative default for stream-open churn per connection. -pub const DEFAULT_ZAKURA_STREAM_OPEN_RATE_PER_SECOND: u32 = 16; +/// Default total Zakura connections when P2P v2 is enabled. +pub const DEFAULT_ZAKURA_MAX_CONNECTIONS: usize = 256; +/// Default simultaneous Zakura control handshakes. +pub const DEFAULT_ZAKURA_MAX_PENDING_HANDSHAKES: usize = 32; +/// Default stream-open churn per connection. +pub const DEFAULT_ZAKURA_STREAM_OPEN_RATE_PER_SECOND: u32 = 32; /// Per-kind inbound message rate per connection. /// /// This is a generous universal cap: block-sync legitimately delivers @@ -111,11 +111,11 @@ pub const DEFAULT_ZAKURA_KEEP_ALIVE_INTERVAL: Duration = Duration::from_secs(10) /// reclaim the slot without disturbing active transfers. pub const ZAKURA_DUPLICATE_EVICT_MIN_AGE: Duration = Duration::from_secs(300); /// QUIC stream receive window used by Zakura endpoints. -pub const DEFAULT_ZAKURA_STREAM_RECEIVE_WINDOW: u32 = 3 * 1024 * 1024; +pub const DEFAULT_ZAKURA_STREAM_RECEIVE_WINDOW: u32 = 32 * 1024 * 1024; /// QUIC connection receive window used by Zakura endpoints. -pub const DEFAULT_ZAKURA_RECEIVE_WINDOW: u32 = 16 * 1024 * 1024; +pub const DEFAULT_ZAKURA_RECEIVE_WINDOW: u32 = 32 * 1024 * 1024; /// QUIC send window used by Zakura endpoints. -pub const DEFAULT_ZAKURA_SEND_WINDOW: u64 = 16 * 1024 * 1024; +pub const DEFAULT_ZAKURA_SEND_WINDOW: u64 = 32 * 1024 * 1024; /// Initial backoff before re-dialing a configured Zakura bootstrap peer. pub const DEFAULT_ZAKURA_REDIAL_INITIAL_BACKOFF: Duration = Duration::from_secs(1); /// Maximum backoff between re-dials of a configured Zakura bootstrap peer. diff --git a/zebrad/tests/common/configs/v5.0.0-rc.4.toml b/zebrad/tests/common/configs/v5.0.0-rc.4.toml new file mode 100644 index 00000000000..fabd8e9bae5 --- /dev/null +++ b/zebrad/tests/common/configs/v5.0.0-rc.4.toml @@ -0,0 +1,169 @@ +# Default configuration for zebrad. +# +# This file can be used as a skeleton for custom configs. +# +# Unspecified fields use default values. Optional fields are Some(field) if the +# field is present and None if it is absent. +# +# This file is generated as an example using zebrad's current defaults. +# You should set only the config options you want to keep, and delete the rest. +# Only a subset of fields are present in the skeleton, since optional values +# whose default is None are omitted. +# +# The config format (including a complete list of sections and fields) is +# documented here: +# https://docs.rs/zebrad/latest/zebrad/config/struct.ZebradConfig.html +# +# CONFIGURATION SOURCES (in order of precedence, highest to lowest): +# +# 1. Environment variables with ZEBRA_ prefix (highest precedence) +# - Format: ZEBRA_SECTION__KEY (double underscore for nested keys) +# - Examples: +# - ZEBRA_NETWORK__NETWORK=Testnet +# - ZEBRA_RPC__LISTEN_ADDR=127.0.0.1:8232 +# - ZEBRA_STATE__CACHE_DIR=/path/to/cache +# - ZEBRA_TRACING__FILTER=debug +# - ZEBRA_METRICS__ENDPOINT_ADDR=0.0.0.0:9999 +# +# 2. Configuration file (TOML format) +# - At the path specified via -c flag, e.g. `zebrad -c myconfig.toml start`, or +# - At the default path in the user's preference directory (platform-dependent, see below) +# +# 3. Hard-coded defaults (lowest precedence) +# +# The user's preference directory and the default path to the `zebrad` config are platform dependent, +# based on `dirs::preference_dir`, see https://docs.rs/dirs/latest/dirs/fn.preference_dir.html : +# +# | Platform | Value | Example | +# | -------- | ------------------------------------- | ---------------------------------------------- | +# | Linux | `$XDG_CONFIG_HOME` or `$HOME/.config` | `/home/alice/.config/zebrad.toml` | +# | macOS | `$HOME/Library/Preferences` | `/Users/Alice/Library/Preferences/zebrad.toml` | +# | Windows | `{FOLDERID_RoamingAppData}` | `C:\Users\Alice\AppData\Local\zebrad.toml` | + +[consensus] +checkpoint_sync = true +disable_vct_fast_sync = false + +[health] +enforce_on_test_networks = false +min_connected_peers = 1 +ready_max_blocks_behind = 2 +ready_max_tip_age = "5m" + +[mempool] +eviction_memory_time = "1h" +max_datacarrier_bytes = 83 +tx_cost_limit = 80000000 + +[metrics] + +[mining] +internal_miner = false + +[network] +cache_dir = true +crawl_new_peer_interval = "1m 1s" +initial_mainnet_peers = [ + "dnsseed.str4d.xyz:8233", + "dnsseed.z.cash:8233", + "mainnet.seeder.shieldedinfra.net:8233", + "mainnet.seeder.zfnd.org:8233", +] +initial_testnet_peers = [ + "dnsseed.testnet.z.cash:18233", + "testnet.seeder.zfnd.org:18233", +] +legacy_p2p = true +listen_addr = "[::]:8233" +max_connections_per_ip = 1 +network = "Mainnet" +peerset_initial_target_size = 100 +v2_p2p = true + +[network.zakura] +bootstrap_peers = [] +listen_addr = "0.0.0.0:8234" +max_connections = 256 +max_pending_handshakes = 32 +message_rate_per_second = 2048 +stream_open_rate_per_second = 32 + +[network.zakura.block_sync] +fanout = 1 +floor_peer_avoid_cooldown = "8s" +floor_watchdog_tick = "1s" +initial_inflight_requests = 64 +max_blocks_per_response = 1 +max_inflight_block_bytes = 6442450944 +max_inflight_requests = 32000 +max_reorder_lookahead_blocks = 4096 +max_reorder_lookahead_bytes = 6408896512 +max_response_bytes = 33554432 +max_submitted_block_applies = 400 +request_timeout = "8s" +size_deviation_tolerance = 200 +status_refresh_interval = "30s" + +[network.zakura.block_sync.peer_limits] +inbound_queue_depth = 128 +max_inbound_peers = 256 +max_outbound_peers = 256 +max_pending_escalations = 32 +outbound_queue_depth = 128 + +[network.zakura.header_sync] +accept_new_blocks = true +max_headers_per_response = 1000 +max_inflight_requests = 10 +status_refresh_interval = "30s" + +[network.zakura.header_sync.peer_limits] +inbound_queue_depth = 128 +max_inbound_peers = 256 +max_outbound_peers = 256 +max_pending_escalations = 32 +outbound_queue_depth = 128 + +[rpc] +cookie_dir = "cache_dir" +cookie_file_name = ".cookie" +debug_force_finished_sync = false +enable_cookie_auth = true +max_response_body_size = 52428800 +parallel_cpu_threads = 0 + +[state] +cache_dir = "cache_dir" +debug_skip_non_finalized_state_backup_task = false +delete_old_database = true +ephemeral = false +should_backup_non_finalized_state = true +storage_mode = "archive" + +[sync] +checkpoint_verify_concurrency_limit = 1000 +download_concurrency_limit = 100 +full_verify_concurrency_limit = 20 +parallel_cpu_threads = 0 +zakura_block_apply_concurrency_limit = 32 + +[tracing] +buffer_limit = 128000 +force_use_color = false +use_color = true +use_journald = false + +[zcashd_compat] +cookie_dir = "cache_dir" +cookie_file_name = ".zcashd-compat.cookie" +enable_cookie_auth = true +enabled = false +manage_zcashd = false +restart_backoff = "2s" +restart_backoff_max = "5m" +restart_reset_after = "1h" +shutdown_grace_period = "5m" +startup_delay = "1s" +unsafe_allow_remote_http = false +zcashd_extra_args = [] +zcashd_source = "path"