v0.2.4-pre.002-fix.001

This commit is contained in:
2026-08-18 20:21:01 +02:00
parent cf8d79567d
commit 033800f897
4 changed files with 196 additions and 4 deletions

View File

@@ -1,12 +1,12 @@
# file: Cargo.toml
# version: 132
# version: 133
[workspace]
resolver = "3"
members = ["crates/ksp-app-config-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-logging-lib", "crates/ksp-onchain-transport-lib"]
[workspace.package]
version = "0.2.4-pre.2"
version = "0.2.4-pre.2.fix.1"
edition = "2024"
license = "MIT"
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/src/rpc_blocks.rs
// version: 1
// version: 2
/// Transaction detail level accepted by modern `getBlock` requests.
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
@@ -82,6 +82,7 @@ impl SolanaGetBlockConfig {
}
/// Returns whether this config would serialize to an empty object.
#[cfg(test)]
pub(crate) const fn is_empty(&self) -> bool {
return self.commitment.is_none()
&& self.encoding.is_none()
@@ -92,6 +93,7 @@ impl SolanaGetBlockConfig {
/// Serializes this config to the exact Solana JSON-RPC object.
#[must_use]
#[cfg(test)]
pub(crate) fn to_json_value(self) -> serde_json::Value {
let mut object = serde_json::Map::new();
if let std::option::Option::Some(commitment) = self.commitment {
@@ -141,6 +143,7 @@ impl SolanaBlockProductionRange {
/// Serializes this range to the exact Solana JSON-RPC object.
#[must_use]
#[cfg(test)]
pub(crate) fn to_json_value(self) -> serde_json::Value {
let mut object = serde_json::Map::new();
object.insert("firstSlot".to_owned(), serde_json::Value::Number(self.first_slot.into()));
@@ -189,12 +192,14 @@ impl SolanaBlockProductionConfig {
}
/// Returns whether this config would serialize to an empty object.
#[cfg(test)]
pub(crate) const fn is_empty(&self) -> bool {
return self.commitment.is_none() && self.identity.is_none() && self.range.is_none();
}
/// Serializes this config to the exact Solana JSON-RPC object.
#[must_use]
#[cfg(test)]
pub(crate) fn to_json_value(&self) -> serde_json::Value {
let mut object = serde_json::Map::new();
if let std::option::Option::Some(commitment) = self.commitment {
@@ -231,6 +236,7 @@ impl SolanaBlockCommitment {
}
/// Decodes a block-commitment result from its Solana JSON wire shape.
#[cfg(test)]
pub(crate) fn decode_wire(method: &str, value: serde_json::Value) -> ksp_core_lib::Result<Self> {
let decoded = crate::decode_wire_json::<WireBlockCommitment>(method, value);
return match decoded {
@@ -282,6 +288,7 @@ impl SolanaBlockProduction {
}
/// Decodes a block-production result from its Solana JSON wire shape.
#[cfg(test)]
pub(crate) fn decode_wire(method: &str, value: serde_json::Value) -> ksp_core_lib::Result<Self> {
let decoded = crate::decode_wire_json::<WireBlockProduction>(method, value);
let wire = match decoded {
@@ -352,6 +359,7 @@ impl SolanaBlockReward {
return &self.commission_bps;
}
#[cfg(test)]
fn decode_wire(method: &str, value: serde_json::Value) -> ksp_core_lib::Result<Self> {
let decoded = crate::decode_wire_json::<WireBlockReward>(method, value);
let wire = match decoded {
@@ -400,6 +408,7 @@ impl SolanaBlockTransaction {
return &self.version;
}
#[cfg(test)]
fn decode_wire(method: &str, value: serde_json::Value) -> ksp_core_lib::Result<Self> {
let decoded = crate::decode_wire_json::<WireBlockTransaction>(method, value);
let wire = match decoded {
@@ -489,6 +498,7 @@ impl SolanaConfirmedBlock {
}
/// Decodes a confirmed block from its Solana JSON wire shape.
#[cfg(test)]
pub(crate) fn decode_wire(method: &str, value: serde_json::Value) -> ksp_core_lib::Result<Self> {
let decoded = crate::decode_wire_json::<WireConfirmedBlock>(method, value);
let wire = match decoded {
@@ -561,6 +571,7 @@ impl SolanaPerformanceSample {
}
/// Decodes one performance sample from its Solana JSON wire shape.
#[cfg(test)]
pub(crate) fn decode_wire(method: &str, value: serde_json::Value) -> ksp_core_lib::Result<Self> {
let decoded = crate::decode_wire_json::<WirePerformanceSample>(method, value);
return match decoded {
@@ -576,6 +587,7 @@ impl SolanaPerformanceSample {
}
}
#[cfg(test)]
fn decode_block_transaction_version(
method: &str,
field: crate::SolanaWireField<serde_json::Value>,
@@ -593,6 +605,7 @@ fn decode_block_transaction_version(
};
}
#[cfg(test)]
fn decode_block_transactions(
method: &str,
field: crate::SolanaWireField<std::vec::Vec<serde_json::Value>>,
@@ -613,6 +626,7 @@ fn decode_block_transactions(
return std::result::Result::Ok(crate::SolanaWireField::Value(transactions));
}
#[cfg(test)]
fn decode_block_rewards(
method: &str,
field: crate::SolanaWireField<std::vec::Vec<serde_json::Value>>,
@@ -633,6 +647,7 @@ fn decode_block_rewards(
return std::result::Result::Ok(crate::SolanaWireField::Value(rewards));
}
#[cfg(test)]
#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct WireBlockCommitment {
@@ -640,6 +655,7 @@ struct WireBlockCommitment {
total_stake: u64,
}
#[cfg(test)]
#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct WireBlockProductionRange {
@@ -647,6 +663,7 @@ struct WireBlockProductionRange {
last_slot: u64,
}
#[cfg(test)]
#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct WireBlockProduction {
@@ -654,6 +671,7 @@ struct WireBlockProduction {
range: WireBlockProductionRange,
}
#[cfg(test)]
#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct WireBlockReward {
@@ -668,6 +686,7 @@ struct WireBlockReward {
commission_bps: crate::SolanaWireField<u16>,
}
#[cfg(test)]
#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct WireBlockTransaction {
@@ -678,6 +697,7 @@ struct WireBlockTransaction {
version: crate::SolanaWireField<serde_json::Value>,
}
#[cfg(test)]
#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct WireConfirmedBlock {
@@ -696,6 +716,7 @@ struct WireConfirmedBlock {
block_height: std::option::Option<u64>,
}
#[cfg(test)]
#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct WirePerformanceSample {

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/src/rpc_economics.rs
// version: 1
// version: 2
/// Inflation-governor values returned by `getInflationGovernor`.
#[derive(Clone, Copy, Debug, PartialEq)]
@@ -43,6 +43,7 @@ impl SolanaInflationGovernor {
}
/// Decodes an inflation-governor result from its Solana JSON wire shape.
#[cfg(test)]
pub(crate) fn decode_wire(method: &str, value: serde_json::Value) -> ksp_core_lib::Result<Self> {
let decoded = crate::decode_wire_json::<WireInflationGovernor>(method, value);
return match decoded {
@@ -93,6 +94,7 @@ impl SolanaInflationRate {
}
/// Decodes an inflation-rate result from its Solana JSON wire shape.
#[cfg(test)]
pub(crate) fn decode_wire(method: &str, value: serde_json::Value) -> ksp_core_lib::Result<Self> {
let decoded = crate::decode_wire_json::<WireInflationRate>(method, value);
return match decoded {
@@ -142,12 +144,14 @@ impl SolanaInflationRewardConfig {
}
/// Returns whether this config would serialize to an empty object.
#[cfg(test)]
pub(crate) const fn is_empty(&self) -> bool {
return self.epoch.is_none() && self.commitment.is_none() && self.min_context_slot.is_none();
}
/// Serializes this config to the exact Solana JSON-RPC object.
#[must_use]
#[cfg(test)]
pub(crate) fn to_json_value(self) -> serde_json::Value {
let mut object = serde_json::Map::new();
if let std::option::Option::Some(epoch) = self.epoch {
@@ -212,6 +216,7 @@ impl SolanaInflationReward {
}
/// Decodes one non-null inflation reward from its Solana JSON wire shape.
#[cfg(test)]
pub(crate) fn decode_wire(method: &str, value: serde_json::Value) -> ksp_core_lib::Result<Self> {
let decoded = crate::decode_wire_json::<WireInflationReward>(method, value);
return match decoded {
@@ -255,12 +260,14 @@ impl SolanaSupplyConfig {
}
/// Returns whether this config would serialize to an empty object.
#[cfg(test)]
pub(crate) const fn is_empty(&self) -> bool {
return self.commitment.is_none() && self.exclude_non_circulating_accounts_list.is_none();
}
/// Serializes this config to the exact Solana JSON-RPC object.
#[must_use]
#[cfg(test)]
pub(crate) fn to_json_value(self) -> serde_json::Value {
let mut object = serde_json::Map::new();
if let std::option::Option::Some(commitment) = self.commitment {
@@ -308,6 +315,7 @@ impl SolanaSupply {
}
/// Decodes a supply result from its Solana JSON wire shape.
#[cfg(test)]
pub(crate) fn decode_wire(method: &str, value: serde_json::Value) -> ksp_core_lib::Result<Self> {
let decoded = crate::decode_wire_json::<WireSupply>(method, value);
let wire = match decoded {
@@ -331,6 +339,7 @@ impl SolanaSupply {
}
}
#[cfg(test)]
#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct WireInflationGovernor {
@@ -341,6 +350,7 @@ struct WireInflationGovernor {
foundation_term: f64,
}
#[cfg(test)]
#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct WireInflationRate {
@@ -350,6 +360,7 @@ struct WireInflationRate {
epoch: u64,
}
#[cfg(test)]
#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct WireInflationReward {
@@ -363,6 +374,7 @@ struct WireInflationReward {
commission_bps: crate::SolanaWireField<u16>,
}
#[cfg(test)]
#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct WireSupply {

View File

@@ -0,0 +1,159 @@
<!-- file: deltas/0.2.4/pre.002-fix.001.md -->
<!-- version: 1 -->
# Delta `0.2.4-pre.002-fix.001` — suppression du code interne prématurément actif
## Base requise
Livraison précédente :
```text
0.2.4-pre.002
workspace.package.version = "0.2.4-pre.2"
```
Ce fix corrige uniquement les warnings `dead_code` introduits par `pre.002` dans les nouveaux modules Blocks/Economics. Il ne redéfinit pas le périmètre fonctionnel de la prerelease et ne modifie ni les DTOs publics, ni les fixtures, ni les tests, ni le registre RPC.
## Problème observé
Les validations locales de `pre.002` ont montré que la tranche est fonctionnellement verte :
```text
cargo fmt --all -> terminé
cargo check --workspace -> terminé avec 29 warnings dead_code
cargo clippy --workspace --all-targets -> terminé avec les mêmes 29 warnings dead_code
cargo test -p ksp-onchain-transport-lib -> 196 unit tests OK
20 public API tests OK
15 release-completeness tests OK
1 smoke Devnet ignoré comme prévu
0 échec
```
Les warnings proviennent exclusivement de helpers internes d'encodage/décodage et de structs `Wire*` préparés en `pre.002` pour les futurs wrappers, alors qu'aucun wrapper `V0_2_4` ne les consomme encore dans une compilation normale de la bibliothèque.
Le choix `#[allow(dead_code)]` est rejeté : le lint est correct et signale du code de production activé trop tôt.
## Correction
Les 17 contrats publics ajoutés par `pre.002` restent compilés et exportés normalement.
Seuls les éléments internes qui n'ont encore aucun consommateur runtime sont placés sous `#[cfg(test)]` :
- helpers `is_empty` des configs Blocks/Economics ;
- helpers `to_json_value` des configs/ranges Blocks/Economics ;
- décodeurs internes `decode_wire` des résultats Blocks/Economics ;
- helpers privés de décodage des transactions/rewards de bloc ;
- structs privées `WireBlock*`, `WirePerformanceSample` et `WireInflation*`/`WireSupply`.
Ils restent donc compilés par les unit tests de `pre.002`, qui continuent à valider les formes wire et les fixtures déterministes, mais ils ne participent plus au build normal de la crate tant qu'un wrapper runtime ne les utilise pas.
Cette approche garde le découpage des prereleases strict :
```text
pre.002 -> contrats publics + fixtures + validation test-only des helpers wire
pre.003+ -> activation progressive des helpers internes au moment où leur wrapper runtime existe
```
À partir de `pre.003`, `SolanaBlockCommitment::decode_wire` sera sorti de `#[cfg(test)]` avec l'implémentation de `getBlockCommitment`. Les autres encodeurs/décodeurs seront activés uniquement dans la prerelease qui introduit leur consommateur.
Aucun `#[allow(dead_code)]` n'est ajouté.
## Version Cargo
Ce correctif modifie des sources Rust participant au build. Conformément à `VER-ID-007` et `VER-ID-010` :
```text
0.2.4-pre.2 -> 0.2.4-pre.2.fix.1
```
Aucune dépendance ni feature Cargo n'est modifiée.
## Fichiers modifiés
```text
Cargo.toml
crates/ksp-onchain-transport-lib/src/rpc_blocks.rs
crates/ksp-onchain-transport-lib/src/rpc_economics.rs
```
## Fichiers ajoutés
```text
deltas/0.2.4/pre.002-fix.001.md
```
## Fichiers supprimés
Aucun.
## Fichiers volontairement inchangés
```text
crates/ksp-onchain-transport-lib/src/lib.rs
crates/ksp-onchain-transport-lib/src/rpc_transactions.rs
crates/ksp-onchain-transport-lib/unit_tests/rpc_blocks.rs
crates/ksp-onchain-transport-lib/unit_tests/rpc_economics.rs
crates/ksp-onchain-transport-lib/tests/public_api.rs
crates/ksp-onchain-transport-lib/tests/release_completeness.rs
crates/ksp-onchain-transport-lib/fixtures/http/**
docs/plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md
ROADMAP.md
CHANGELOG.md
deltas/0.2.4/pre.002.md
```
Aucun delta historique n'est réécrit.
## Validations exécutées dans le sandbox
- contrôle différentiel contre la livraison `pre.002` ;
- vérification que seuls les trois fichiers de production listés ci-dessus sont modifiés ;
- contrôle que les 17 types publics de `pre.002` restent hors `#[cfg(test)]` ;
- contrôle que tous les helpers et structs privés signalés `dead_code` par les validations locales sont maintenant test-only ;
- contrôle de l'absence de `#[allow(dead_code)]` ;
- contrôle de l'absence de `unwrap`, `expect`, `panic!` et `unsafe` dans les lignes modifiées ;
- `git diff --check` sur le fix ;
- contrôle des versions de fichiers modifiés.
## Validations Cargo non exécutées dans le sandbox
Le sandbox ne fournit pas `cargo`, `rustc` ni `rustfmt`. Les validations du fix doivent donc être rejouées sur le checkout de développement :
```bash
cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-onchain-transport-lib
```
Le critère de clôture du fix est plus strict que pour la tentative initiale : `cargo check` et `cargo clippy` doivent terminer sans les 29 warnings `dead_code` introduits par `pre.002`.
Le commit attendu après validation est :
```text
v0.2.4-pre.002-fix.001
```
## Décisions prises
- conserver les DTOs publics actifs en production ;
- rendre test-only uniquement l'infrastructure wire interne sans consommateur runtime ;
- ne pas masquer les warnings avec `allow(dead_code)` ;
- activer progressivement les helpers lors de l'arrivée de chaque wrapper ;
- ne pas modifier le plan `011`, le périmètre fonctionnel restant identique.
## Questions ouvertes
Aucune.
## Suite
Après validation du fix, `0.2.4-pre.003` reste inchangé :
```text
getBlockCommitment
getBlockHeight
getBlockTime
getFirstAvailableBlock
minimumLedgerSlot
```