From 1780cd7ede47a5f3da6448cb1a82d86d6c644e33 Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sun, 20 Sep 2026 13:54:48 +0100 Subject: [PATCH 1/2] repair: add the V1 declarative repair schema Add RepairContextV1, RepairEffectsV1, and RepairFixtureV1 (plus the nested RepairSlotDescV1, RepairGapV1, RepairPeerV1, and RepairShredIdV1 messages) for the sol_compat_repair_v1 differential target. The schema describes a repair-stack scenario declaratively: a slot topology, a set of shred/FEC-set/slot gaps to repair, and run configuration (peers, publish slot, insertion order, turbine/elapsed- time overrides). Co-Authored-By: Claude Sonnet 5 --- Cargo.lock | 2 +- Cargo.toml | 2 +- proto/repair.options | 11 ++ proto/repair.proto | 93 +++++++++++++++++ src/generated/file_descriptor_set.bin | Bin 66905 -> 72476 bytes src/generated/org.solana.sealevel.v1.rs | 127 ++++++++++++++++++++++++ 6 files changed, 233 insertions(+), 2 deletions(-) create mode 100644 proto/repair.options create mode 100644 proto/repair.proto diff --git a/Cargo.lock b/Cargo.lock index 9aa92b9..eedf678 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -399,7 +399,7 @@ dependencies = [ [[package]] name = "protosol" -version = "18.0.0" +version = "19.0.0" dependencies = [ "prost", "prost-build", diff --git a/Cargo.toml b/Cargo.toml index b7ca46f..aef9ee5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "protosol" -version = "18.0.0" +version = "19.0.0" edition = "2021" license = "Apache-2.0" description = "Protobuf definitions for the SVM fuzzing project." diff --git a/proto/repair.options b/proto/repair.options new file mode 100644 index 0000000..a709013 --- /dev/null +++ b/proto/repair.options @@ -0,0 +1,11 @@ +repair.proto package:"fd_exec_test" +repair.proto include:"../../../../ballet/nanopb/pb_firedancer.h" + +fd_exec_test.RepairContextV1.slots type:FT_POINTER +fd_exec_test.RepairContextV1.gaps type:FT_POINTER +fd_exec_test.RepairContextV1.insertion_order type:FT_POINTER +fd_exec_test.RepairContextV1.turbine_slots type:FT_POINTER +fd_exec_test.RepairContextV1.peers type:FT_POINTER + +fd_exec_test.RepairEffectsV1.recovered type:FT_POINTER +fd_exec_test.RepairEffectsV1.dropped_slots type:FT_POINTER diff --git a/proto/repair.proto b/proto/repair.proto new file mode 100644 index 0000000..52c4bb5 --- /dev/null +++ b/proto/repair.proto @@ -0,0 +1,93 @@ +syntax = "proto3"; +package org.solana.sealevel.v1; + +import "metadata.proto"; + +// Differential harness for repair (sol_compat_repair_v1). + +message RepairSlotDescV1 { + uint64 slot = 1; + // Parent registered before any shreds arrive (cf. shred_parent_slot). + uint64 parent_slot = 2; + uint32 fec_set_cnt = 3; + // Data shreds per FEC set; must be 32 (DATA_SHREDS_PER_FEC_BLOCK). + uint32 shreds_per_fec = 4; + // Parent actually embedded in delivered shreds, if it disagrees with + // parent_slot (equivocation). + optional uint64 shred_parent_slot = 5; +} + +message RepairGapShredV1 { + uint64 slot = 1; + uint32 shred_idx = 2; +} + +message RepairGapFecSetV1 { + uint64 slot = 1; + uint32 fec_set_idx = 2; +} + +// Determined at startup, before any repair round runs. +message RepairGapV1 { + oneof gap { + RepairGapShredV1 shred = 1; + RepairGapFecSetV1 fec_set = 2; + // All shreds in the slot, not just one FEC set. + uint64 slot = 3; + } +} + +message RepairPeerV1 { + // 2..255; peer 1 always exists. + uint32 peer_id = 1; + // If set, simulate a repair response with this RTT (ns), aging the peer into + // the fast/slow list. + optional int64 rtt_ns = 2; +} + +message RepairContextV1 { + uint64 root_slot = 1; + repeated RepairSlotDescV1 slots = 2; + repeated RepairGapV1 gaps = 3; + // Max repair requests per round (default 32). + optional uint32 max_requests_per_round = 4; + // Override fd_forest slot_max (must be a power of two); models pool pressure + // to reach the eviction path's force-root escape hatch. + optional uint64 slot_max_override = 5; + // Override fd_reqlim dedup_max (default 1024). + optional uint64 dedup_max_override = 6; + // Insert slots in this order (indices into `slots`) instead of natural order. + repeated uint32 insertion_order = 7; + // Advance the root to this slot after the first gap shred is delivered. + optional uint64 publish_slot = 8; + // Slots whose non-gap shreds are delivered as turbine source (sets ref_tick=1 + // on FD's side). + repeated uint64 turbine_slots = 9; + // Slots >= this are subject to the turbine throttle. + optional uint64 turbine_slot0 = 10; + repeated RepairPeerV1 peers = 11; + // Simulated ms elapsed since a slot's first shred, for repair-eligibility + // throttles; unset = fully elapsed. + optional uint64 elapsed_ms = 12; +} + +message RepairShredIdV1 { + uint64 slot = 1; + uint32 shred_idx = 2; +} + +message RepairEffectsV1 { + // True if the internal driver reached completion within its round budget. + bool converged = 1; + // Sorted by (slot, shred_idx). + repeated RepairShredIdV1 recovered = 2; + // Slots dropped by the implementation (e.g. FD bounded-pool eviction); sorted + // ascending. + repeated uint64 dropped_slots = 3; +} + +message RepairFixtureV1 { + FixtureMetadata metadata = 1; + RepairContextV1 input = 2; + RepairEffectsV1 output = 3; +} diff --git a/src/generated/file_descriptor_set.bin b/src/generated/file_descriptor_set.bin index 4aa17bb8e9472e55687c050de8d845350240ec12..2896249ce1a66d8ab64ffc282d41ad4a6d70570f 100644 GIT binary patch delta 5195 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, } +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct RepairSlotDescV1 { + #[prost(uint64, tag = "1")] + pub slot: u64, + /// Parent registered before any shreds arrive (cf. shred_parent_slot). + #[prost(uint64, tag = "2")] + pub parent_slot: u64, + #[prost(uint32, tag = "3")] + pub fec_set_cnt: u32, + /// Data shreds per FEC set; must be 32 (DATA_SHREDS_PER_FEC_BLOCK). + #[prost(uint32, tag = "4")] + pub shreds_per_fec: u32, + /// Parent actually embedded in delivered shreds, if it disagrees with + /// parent_slot (equivocation). + #[prost(uint64, optional, tag = "5")] + pub shred_parent_slot: ::core::option::Option, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct RepairGapShredV1 { + #[prost(uint64, tag = "1")] + pub slot: u64, + #[prost(uint32, tag = "2")] + pub shred_idx: u32, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct RepairGapFecSetV1 { + #[prost(uint64, tag = "1")] + pub slot: u64, + #[prost(uint32, tag = "2")] + pub fec_set_idx: u32, +} +/// Determined at startup, before any repair round runs. +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct RepairGapV1 { + #[prost(oneof = "repair_gap_v1::Gap", tags = "1, 2, 3")] + pub gap: ::core::option::Option, +} +/// Nested message and enum types in `RepairGapV1`. +pub mod repair_gap_v1 { + #[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Gap { + #[prost(message, tag = "1")] + Shred(super::RepairGapShredV1), + #[prost(message, tag = "2")] + FecSet(super::RepairGapFecSetV1), + /// All shreds in the slot, not just one FEC set. + #[prost(uint64, tag = "3")] + Slot(u64), + } +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct RepairPeerV1 { + /// 2..255; peer 1 always exists. + #[prost(uint32, tag = "1")] + pub peer_id: u32, + /// If set, simulate a repair response with this RTT (ns), aging the peer into + /// the fast/slow list. + #[prost(int64, optional, tag = "2")] + pub rtt_ns: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RepairContextV1 { + #[prost(uint64, tag = "1")] + pub root_slot: u64, + #[prost(message, repeated, tag = "2")] + pub slots: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "3")] + pub gaps: ::prost::alloc::vec::Vec, + /// Max repair requests per round (default 32). + #[prost(uint32, optional, tag = "4")] + pub max_requests_per_round: ::core::option::Option, + /// Override fd_forest slot_max (must be a power of two); models pool pressure + /// to reach the eviction path's force-root escape hatch. + #[prost(uint64, optional, tag = "5")] + pub slot_max_override: ::core::option::Option, + /// Override fd_reqlim dedup_max (default 1024). + #[prost(uint64, optional, tag = "6")] + pub dedup_max_override: ::core::option::Option, + /// Insert slots in this order (indices into `slots`) instead of natural order. + #[prost(uint32, repeated, tag = "7")] + pub insertion_order: ::prost::alloc::vec::Vec, + /// Advance the root to this slot after the first gap shred is delivered. + #[prost(uint64, optional, tag = "8")] + pub publish_slot: ::core::option::Option, + /// Slots whose non-gap shreds are delivered as turbine source (sets ref_tick=1 + /// on FD's side). + #[prost(uint64, repeated, tag = "9")] + pub turbine_slots: ::prost::alloc::vec::Vec, + /// Slots >= this are subject to the turbine throttle. + #[prost(uint64, optional, tag = "10")] + pub turbine_slot0: ::core::option::Option, + #[prost(message, repeated, tag = "11")] + pub peers: ::prost::alloc::vec::Vec, + /// Simulated ms elapsed since a slot's first shred, for repair-eligibility + /// throttles; unset = fully elapsed. + #[prost(uint64, optional, tag = "12")] + pub elapsed_ms: ::core::option::Option, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct RepairShredIdV1 { + #[prost(uint64, tag = "1")] + pub slot: u64, + #[prost(uint32, tag = "2")] + pub shred_idx: u32, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RepairEffectsV1 { + /// True if the internal driver reached completion within its round budget. + #[prost(bool, tag = "1")] + pub converged: bool, + /// Sorted by (slot, shred_idx). + #[prost(message, repeated, tag = "2")] + pub recovered: ::prost::alloc::vec::Vec, + /// Slots dropped by the implementation (e.g. FD bounded-pool eviction); sorted + /// ascending. + #[prost(uint64, repeated, tag = "3")] + pub dropped_slots: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RepairFixtureV1 { + #[prost(message, optional, tag = "1")] + pub metadata: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub input: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub output: ::core::option::Option, +} /// Any features that needed to be fuzzed should be manually added here. /// Once they're cleaned up / activated on all clusters, they can be /// removed via a reserved tag. From 36ab16fcc053b3702201886849999b7358ca847b Mon Sep 17 00:00:00 2001 From: Peter Schrammel Date: Sun, 20 Sep 2026 13:56:13 +0100 Subject: [PATCH 2/2] repair: add the V2 event-trace repair schema Add RepairContextV2, RepairEffectsV2, and RepairFixtureV2 (plus the nested RepairChainSlot, RepairShredSource, RepairShredKind, DeliverShred, ServeRequests, Confirm, SetRoot, PeerFault, AdvanceTime, RepairEvent, RepairSlotState, RepairSnapshot, RepairRequestKind, and RepairRequest messages) for the sol_compat_repair_v2 differential target. The schema describes a repair-stack scenario as a ground-truth chain plus an ordered event trace (deliver/serve/confirm/set_root/fault/time) that the target's driver applies in order, reporting the sequence of resulting states. Co-Authored-By: Claude Sonnet 5 --- Cargo.lock | 2 +- Cargo.toml | 2 +- proto/repair.options | 10 + proto/repair.proto | 174 ++++++++++++++ src/generated/file_descriptor_set.bin | Bin 72476 -> 82395 bytes src/generated/org.solana.sealevel.v1.rs | 294 ++++++++++++++++++++++++ 6 files changed, 480 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eedf678..3b00a7f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -399,7 +399,7 @@ dependencies = [ [[package]] name = "protosol" -version = "19.0.0" +version = "20.0.0" dependencies = [ "prost", "prost-build", diff --git a/Cargo.toml b/Cargo.toml index aef9ee5..ac78ed8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "protosol" -version = "19.0.0" +version = "20.0.0" edition = "2021" license = "Apache-2.0" description = "Protobuf definitions for the SVM fuzzing project." diff --git a/proto/repair.options b/proto/repair.options index a709013..0dd1107 100644 --- a/proto/repair.options +++ b/proto/repair.options @@ -9,3 +9,13 @@ fd_exec_test.RepairContextV1.peers type:FT_POINTER fd_exec_test.RepairEffectsV1.recovered type:FT_POINTER fd_exec_test.RepairEffectsV1.dropped_slots type:FT_POINTER + +fd_exec_test.RepairContextV2.peer_ids type:FT_POINTER +fd_exec_test.RepairContextV2.chain type:FT_POINTER +fd_exec_test.RepairContextV2.events type:FT_POINTER + +fd_exec_test.RepairSnapshot.slots type:FT_POINTER + +fd_exec_test.RepairEffectsV2.snapshots type:FT_POINTER +fd_exec_test.RepairEffectsV2.requests type:FT_POINTER +fd_exec_test.RepairEffectsV2.evicted_slots type:FT_POINTER diff --git a/proto/repair.proto b/proto/repair.proto index 52c4bb5..60661ee 100644 --- a/proto/repair.proto +++ b/proto/repair.proto @@ -91,3 +91,177 @@ message RepairFixtureV1 { RepairContextV1 input = 2; RepairEffectsV1 output = 3; } + +// Differential harness for repair (sol_compat_repair_v2). The context contains +// ground truth information (`chain`) plus an ordered `RepairEvent` trace that +// describes the test scenario. + +// The responder serves shreds from this. +message RepairChainSlot { + uint64 slot = 1; + uint64 parent_slot = 2; + // Number of FEC sets, 1..=8; each is exactly 32 data shreds. + uint32 fec_set_cnt = 3; +} + +enum RepairShredSource { + REPAIR_SRC_TURBINE = 0; + REPAIR_SRC_REPAIR = 1; +} + +enum RepairShredKind { + REPAIR_SHRED_DATA = 0; + REPAIR_SHRED_CODE = 1; +} + +// Inject part of one FEC set regardless of whether it was requested -- the +// adversarial channel: arrival ordering, equivocating versions, premature slot +// completion, orphan creation. Unit is a FEC set, not a shred, since that's +// the unit both implementations work in. fec_set_idx and slot_complete are +// derived (fec_idx*32; index == fec_set_cnt*32-1), not stored. +message DeliverShred { + uint64 slot = 1; + // Parent these shreds CLAIM; may disagree with the chain (equivocation), not + // clamped. + uint64 parent_slot = 2; + // 0-based. + uint32 fec_idx = 3; + // Bit i selects shred i of the FEC set (absolute index fec_idx*32 + i); a + // cleared bit is a gap. + uint32 shred_mask = 4; + // Byte-version of the block these shreds belong to (its merkle root); + // differing versions model equivocation. + uint32 version = 5; + // FEC-set count of the version these shreds belong to; unset = ground truth's + // count. Models false slot completion. + optional uint32 fec_set_cnt = 6; + // Sets ref_tick (1 if turbine, 0 if repair), FD's per-shred receipt-time feed + // into eligibility timing. + RepairShredSource src = 7; + // Peer these shreds are attributed to; 1 (the default peer) or listed in + // RepairContextV2.peer_ids. + uint32 peer_id = 8; + // Coding shreds count toward the Reed-Solomon recovery threshold. + RepairShredKind kind = 9; +} + +// Feeds the implementation's own outbound requests through the ground-truth +// responder, answering up to `max_n`. +message ServeRequests { + uint32 max_n = 1; +} + +// Consensus signal: the slot was confirmed at `level` (gates FD's +// chain_confirmed / confirmed_bid bookkeeping). +message Confirm { + uint64 slot = 1; + // Byte-version of the block that was confirmed. + uint32 version = 2; + uint32 level = 3; +} + +// Advance the root, as a consensus-driven root change would. Not clamped; +// the repair driver gates the actual advance. +message SetRoot { + uint64 slot = 1; +} + +// Fields apply independently. +message PeerFault { + uint32 peer_id = 1; + // If set, record a repair response with this RTT (ns), aging the peer into + // the fast/slow list. + optional int64 rtt_ns = 2; + // If true, drop requests hashing to this peer, by a predicate both targets + // run identically. + bool unresponsive = 3; +} + +// Simulate wall-clock time passing for both sides' repair-eligibility +// throttles, by back-dating timestamps (never sleeping). +message AdvanceTime { + uint64 ms = 1; +} + +message RepairEvent { + oneof event { + DeliverShred deliver = 1; + ServeRequests serve = 2; + Confirm confirm = 3; + SetRoot set_root = 4; + PeerFault fault = 5; + AdvanceTime time = 6; + } +} + +message RepairContextV2 { + uint64 root_slot = 1; + // FD forest pool size, rounded up to a power of two; 0 = default. Not clamped + // to the trace's slot count -- models pool pressure to reach the eviction + // path's force-root escape hatch. + uint32 slot_max = 2; + // fd_reqlim dedup map size (power of two). 0 selects a default. + uint32 dedup_max = 3; + // 2..=255; peer 1 always exists. + repeated uint32 peer_ids = 4; + repeated RepairChainSlot chain = 5; + repeated RepairEvent events = 6; + // Slots >= this are subject to FD's turbine grace period; unset leaves the + // throttle inactive. + optional uint64 turbine_slot0 = 7; +} + +// One slot's observable state; deliberately raw (indices, not a derived "is +// complete" bit). +message RepairSlotState { + uint64 slot = 1; + uint64 parent_slot = 2; + // Highest contiguous buffered data shred index; UINT32_MAX if none. + uint32 buffered_idx = 3; + // Index carrying SLOT_COMPLETE; UINT32_MAX if not yet known. + uint32 complete_idx = 4; + // Every FEC set in the slot has been chain-verified. + bool chain_confirmed = 5; +} + +// The implementation's live state after one event; `slots` is the set the hard +// check diffs against the other target. +message RepairSnapshot { + // Index into RepairContextV2.events of the event that produced this snapshot. + uint32 event_idx = 1; + uint64 root = 2; + // Sorted ascending by slot. + repeated RepairSlotState slots = 3; + // Diagnostic only: most recent ServeRequests fetched nothing new on this + // side. + bool settled = 4; +} + +enum RepairRequestKind { + REPAIR_REQ_SHRED = 0; + REPAIR_REQ_HIGHEST_SHRED = 1; + REPAIR_REQ_ORPHAN = 2; +} + +// One outbound repair request; metric only, never equality-checked. +message RepairRequest { + RepairRequestKind kind = 1; + uint64 slot = 2; + uint32 shred_idx = 3; + uint32 event_idx = 4; +} + +message RepairEffectsV2 { + repeated RepairSnapshot snapshots = 1; + // Metrics tier, never equality-checked. + repeated RepairRequest requests = 2; + // Slots dropped without the root advancing past them (FD bounded-pool + // eviction); sorted ascending. + repeated uint64 evicted_slots = 3; +} + +message RepairFixtureV2 { + FixtureMetadata metadata = 1; + RepairContextV2 input = 2; + RepairEffectsV2 output = 3; +} diff --git a/src/generated/file_descriptor_set.bin b/src/generated/file_descriptor_set.bin index 2896249ce1a66d8ab64ffc282d41ad4a6d70570f..502c72058c4260d71216faa6bcb2e3f590311fb7 100644 GIT binary patch delta 9024 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 EW33tye*gdg diff --git a/src/generated/org.solana.sealevel.v1.rs b/src/generated/org.solana.sealevel.v1.rs index 8e048b9..70e92a3 100644 --- a/src/generated/org.solana.sealevel.v1.rs +++ b/src/generated/org.solana.sealevel.v1.rs @@ -1173,6 +1173,300 @@ pub struct RepairFixtureV1 { #[prost(message, optional, tag = "3")] pub output: ::core::option::Option, } +/// The responder serves shreds from this. +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct RepairChainSlot { + #[prost(uint64, tag = "1")] + pub slot: u64, + #[prost(uint64, tag = "2")] + pub parent_slot: u64, + /// Number of FEC sets, 1..=8; each is exactly 32 data shreds. + #[prost(uint32, tag = "3")] + pub fec_set_cnt: u32, +} +/// Inject part of one FEC set regardless of whether it was requested -- the +/// adversarial channel: arrival ordering, equivocating versions, premature slot +/// completion, orphan creation. Unit is a FEC set, not a shred, since that's +/// the unit both implementations work in. fec_set_idx and slot_complete are +/// derived (fec_idx*32; index == fec_set_cnt*32-1), not stored. +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct DeliverShred { + #[prost(uint64, tag = "1")] + pub slot: u64, + /// Parent these shreds CLAIM; may disagree with the chain (equivocation), not + /// clamped. + #[prost(uint64, tag = "2")] + pub parent_slot: u64, + /// 0-based. + #[prost(uint32, tag = "3")] + pub fec_idx: u32, + /// Bit i selects shred i of the FEC set (absolute index fec_idx*32 + i); a + /// cleared bit is a gap. + #[prost(uint32, tag = "4")] + pub shred_mask: u32, + /// Byte-version of the block these shreds belong to (its merkle root); + /// differing versions model equivocation. + #[prost(uint32, tag = "5")] + pub version: u32, + /// FEC-set count of the version these shreds belong to; unset = ground truth's + /// count. Models false slot completion. + #[prost(uint32, optional, tag = "6")] + pub fec_set_cnt: ::core::option::Option, + /// Sets ref_tick (1 if turbine, 0 if repair), FD's per-shred receipt-time feed + /// into eligibility timing. + #[prost(enumeration = "RepairShredSource", tag = "7")] + pub src: i32, + /// Peer these shreds are attributed to; 1 (the default peer) or listed in + /// RepairContextV2.peer_ids. + #[prost(uint32, tag = "8")] + pub peer_id: u32, + /// Coding shreds count toward the Reed-Solomon recovery threshold. + #[prost(enumeration = "RepairShredKind", tag = "9")] + pub kind: i32, +} +/// Feeds the implementation's own outbound requests through the ground-truth +/// responder, answering up to `max_n`. +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ServeRequests { + #[prost(uint32, tag = "1")] + pub max_n: u32, +} +/// Consensus signal: the slot was confirmed at `level` (gates FD's +/// chain_confirmed / confirmed_bid bookkeeping). +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Confirm { + #[prost(uint64, tag = "1")] + pub slot: u64, + /// Byte-version of the block that was confirmed. + #[prost(uint32, tag = "2")] + pub version: u32, + #[prost(uint32, tag = "3")] + pub level: u32, +} +/// Advance the root, as a consensus-driven root change would. Not clamped; +/// the repair driver gates the actual advance. +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct SetRoot { + #[prost(uint64, tag = "1")] + pub slot: u64, +} +/// Fields apply independently. +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct PeerFault { + #[prost(uint32, tag = "1")] + pub peer_id: u32, + /// If set, record a repair response with this RTT (ns), aging the peer into + /// the fast/slow list. + #[prost(int64, optional, tag = "2")] + pub rtt_ns: ::core::option::Option, + /// If true, drop requests hashing to this peer, by a predicate both targets + /// run identically. + #[prost(bool, tag = "3")] + pub unresponsive: bool, +} +/// Simulate wall-clock time passing for both sides' repair-eligibility +/// throttles, by back-dating timestamps (never sleeping). +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct AdvanceTime { + #[prost(uint64, tag = "1")] + pub ms: u64, +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct RepairEvent { + #[prost(oneof = "repair_event::Event", tags = "1, 2, 3, 4, 5, 6")] + pub event: ::core::option::Option, +} +/// Nested message and enum types in `RepairEvent`. +pub mod repair_event { + #[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Oneof)] + pub enum Event { + #[prost(message, tag = "1")] + Deliver(super::DeliverShred), + #[prost(message, tag = "2")] + Serve(super::ServeRequests), + #[prost(message, tag = "3")] + Confirm(super::Confirm), + #[prost(message, tag = "4")] + SetRoot(super::SetRoot), + #[prost(message, tag = "5")] + Fault(super::PeerFault), + #[prost(message, tag = "6")] + Time(super::AdvanceTime), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RepairContextV2 { + #[prost(uint64, tag = "1")] + pub root_slot: u64, + /// FD forest pool size, rounded up to a power of two; 0 = default. Not clamped + /// to the trace's slot count -- models pool pressure to reach the eviction + /// path's force-root escape hatch. + #[prost(uint32, tag = "2")] + pub slot_max: u32, + /// fd_reqlim dedup map size (power of two). 0 selects a default. + #[prost(uint32, tag = "3")] + pub dedup_max: u32, + /// 2..=255; peer 1 always exists. + #[prost(uint32, repeated, tag = "4")] + pub peer_ids: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "5")] + pub chain: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "6")] + pub events: ::prost::alloc::vec::Vec, + /// Slots >= this are subject to FD's turbine grace period; unset leaves the + /// throttle inactive. + #[prost(uint64, optional, tag = "7")] + pub turbine_slot0: ::core::option::Option, +} +/// One slot's observable state; deliberately raw (indices, not a derived "is +/// complete" bit). +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct RepairSlotState { + #[prost(uint64, tag = "1")] + pub slot: u64, + #[prost(uint64, tag = "2")] + pub parent_slot: u64, + /// Highest contiguous buffered data shred index; UINT32_MAX if none. + #[prost(uint32, tag = "3")] + pub buffered_idx: u32, + /// Index carrying SLOT_COMPLETE; UINT32_MAX if not yet known. + #[prost(uint32, tag = "4")] + pub complete_idx: u32, + /// Every FEC set in the slot has been chain-verified. + #[prost(bool, tag = "5")] + pub chain_confirmed: bool, +} +/// The implementation's live state after one event; `slots` is the set the hard +/// check diffs against the other target. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RepairSnapshot { + /// Index into RepairContextV2.events of the event that produced this snapshot. + #[prost(uint32, tag = "1")] + pub event_idx: u32, + #[prost(uint64, tag = "2")] + pub root: u64, + /// Sorted ascending by slot. + #[prost(message, repeated, tag = "3")] + pub slots: ::prost::alloc::vec::Vec, + /// Diagnostic only: most recent ServeRequests fetched nothing new on this + /// side. + #[prost(bool, tag = "4")] + pub settled: bool, +} +/// One outbound repair request; metric only, never equality-checked. +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct RepairRequest { + #[prost(enumeration = "RepairRequestKind", tag = "1")] + pub kind: i32, + #[prost(uint64, tag = "2")] + pub slot: u64, + #[prost(uint32, tag = "3")] + pub shred_idx: u32, + #[prost(uint32, tag = "4")] + pub event_idx: u32, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RepairEffectsV2 { + #[prost(message, repeated, tag = "1")] + pub snapshots: ::prost::alloc::vec::Vec, + /// Metrics tier, never equality-checked. + #[prost(message, repeated, tag = "2")] + pub requests: ::prost::alloc::vec::Vec, + /// Slots dropped without the root advancing past them (FD bounded-pool + /// eviction); sorted ascending. + #[prost(uint64, repeated, tag = "3")] + pub evicted_slots: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RepairFixtureV2 { + #[prost(message, optional, tag = "1")] + pub metadata: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub input: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub output: ::core::option::Option, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum RepairShredSource { + RepairSrcTurbine = 0, + RepairSrcRepair = 1, +} +impl RepairShredSource { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::RepairSrcTurbine => "REPAIR_SRC_TURBINE", + Self::RepairSrcRepair => "REPAIR_SRC_REPAIR", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "REPAIR_SRC_TURBINE" => Some(Self::RepairSrcTurbine), + "REPAIR_SRC_REPAIR" => Some(Self::RepairSrcRepair), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum RepairShredKind { + RepairShredData = 0, + RepairShredCode = 1, +} +impl RepairShredKind { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::RepairShredData => "REPAIR_SHRED_DATA", + Self::RepairShredCode => "REPAIR_SHRED_CODE", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "REPAIR_SHRED_DATA" => Some(Self::RepairShredData), + "REPAIR_SHRED_CODE" => Some(Self::RepairShredCode), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum RepairRequestKind { + RepairReqShred = 0, + RepairReqHighestShred = 1, + RepairReqOrphan = 2, +} +impl RepairRequestKind { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::RepairReqShred => "REPAIR_REQ_SHRED", + Self::RepairReqHighestShred => "REPAIR_REQ_HIGHEST_SHRED", + Self::RepairReqOrphan => "REPAIR_REQ_ORPHAN", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "REPAIR_REQ_SHRED" => Some(Self::RepairReqShred), + "REPAIR_REQ_HIGHEST_SHRED" => Some(Self::RepairReqHighestShred), + "REPAIR_REQ_ORPHAN" => Some(Self::RepairReqOrphan), + _ => None, + } + } +} /// Any features that needed to be fuzzed should be manually added here. /// Once they're cleaned up / activated on all clusters, they can be /// removed via a reserved tag.