v0.2.4-pre.001-fix.001
This commit is contained in:
191
deltas/0.2.4/pre.001-fix.001.md
Normal file
191
deltas/0.2.4/pre.001-fix.001.md
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
<!-- file: deltas/0.2.4/pre.001-fix.001.md -->
|
||||||
|
<!-- version: 1 -->
|
||||||
|
|
||||||
|
# Delta `0.2.4-pre.001-fix.001` — audit SIMD Transport et correction des matrices du plan
|
||||||
|
|
||||||
|
## Base requise
|
||||||
|
|
||||||
|
Ce fix s'applique après :
|
||||||
|
|
||||||
|
```text
|
||||||
|
0.2.4-pre.001
|
||||||
|
workspace.package.version = "0.2.4-pre.1"
|
||||||
|
```
|
||||||
|
|
||||||
|
Le delta historique `deltas/0.2.4/pre.001.md` reste inchangé.
|
||||||
|
|
||||||
|
## Motif du fix
|
||||||
|
|
||||||
|
Deux corrections documentaires sont nécessaires avant `pre.002` :
|
||||||
|
|
||||||
|
1. les matrices Blocks/Economics du plan utilisaient des caractères `|` à l'intérieur de cellules Markdown, notamment dans des unions telles que `object | null`; certains renderers les interprètent comme des séparateurs de colonnes même lorsqu'ils sont placés dans du code inline ;
|
||||||
|
2. l'apparition de `commissionBps` liée à SIMD-0291 impose de vérifier systématiquement si d'autres SIMDs actuels ou proches de la baseline stable affectent la surface HTTP couverte par `KSP-TRANSPORT-007`.
|
||||||
|
|
||||||
|
Ce fix ne modifie aucun wrapper ni source Rust. Il complète le plan avant l'implémentation afin que les modifications nécessaires soient réalisées dans les prereleases fonctionnelles prévues.
|
||||||
|
|
||||||
|
## Audit SIMD `KSP-TRANSPORT-007`
|
||||||
|
|
||||||
|
Le critère retenu est le wire réellement supporté par la baseline Solana/Agave stable, pas le seul statut administratif d'un SIMD. Un SIMD encore en `Review` peut donc être pertinent si Agave stable expose déjà un champ de compatibilité ; inversement, un champ proposé mais absent d'Agave stable n'est pas inventé par KSP.
|
||||||
|
|
||||||
|
### SIMD à prendre en compte dans `0.2.4`
|
||||||
|
|
||||||
|
**SIMD-0118 — Partitioned Epoch Rewards Distribution**
|
||||||
|
|
||||||
|
- statut actuel : `Activated` ;
|
||||||
|
- impact HTTP direct : `getBlock.numRewardPartitions` ;
|
||||||
|
- Agave `v4.2.1` expose `UiConfirmedBlock.num_reward_partitions: Option<u64>` ;
|
||||||
|
- le futur DTO bloc KSP doit préserver la présence/omission du champ, sans synthétiser `0` ;
|
||||||
|
- le plan retient `SolanaWireField<u64>` ou une représentation wire équivalente et des fixtures `present`/`omitted`.
|
||||||
|
|
||||||
|
**SIMD-0291 — Commission Rate in Basis Points**
|
||||||
|
|
||||||
|
- statut actuel du document SIMD : `Review` ;
|
||||||
|
- Agave stable `v4.2.1` expose néanmoins déjà les champs RPC de compatibilité en basis points ;
|
||||||
|
- `getVoteAccounts.inflationRewardsCommissionBps` est déjà implémenté et testé par la surface `0.2.2` : aucune remédiation des 37 wrappers acquis ;
|
||||||
|
- `getBlock.rewards[].commissionBps` doit être conservé dans un reward wire de bloc dédié ;
|
||||||
|
- `getInflationReward[].commissionBps` doit être conservé dans le DTO d'inflation reward ;
|
||||||
|
- `commission` reste nullable et `commissionBps` reste optionnel/omis ; KSP ne dérive pas l'un depuis l'autre ;
|
||||||
|
- `getTransaction.meta` de `0.2.3` est déjà lossless en `serde_json::Value`, donc les rewards imbriqués ne perdent pas cette extension.
|
||||||
|
|
||||||
|
### SIMDs déjà couverts ou sans nouveau wire immédiat
|
||||||
|
|
||||||
|
**SIMD-0185 — Vote Account v4** est `Accepted`. Les évolutions des account parsers restent compatibles avec `SolanaParsedAccountData.parsed: serde_json::Value`. Le DTO stable `RpcVoteAccountInfo` d'Agave `v4.2.1` n'expose pas les collector fields de Vote Account v4 ; KSP ne les ajoute pas spéculativement à `SolanaVoteAccountInfo`.
|
||||||
|
|
||||||
|
**SIMD-0186 — Loaded Transaction Data Size Specification** est `Accepted`. `simulateTransaction.loadedAccountsDataSize` est déjà préservé dans `0.2.3` via `SolanaWireField<u32>` avec couverture de l'omission. Transport restitue cette valeur runtime et ne la recalcule pas.
|
||||||
|
|
||||||
|
**SIMD-0385 — Transaction V1 Format** est en `Review`. Le contrat KSP actuel est déjà future-compatible parce que `SolanaTransactionVersion::Number(u8)` n'est pas limité à la version `0` et les payloads JSON restent lossless. Le plan ajoute toutefois une canary avec une version numérique non nulle et impose la même propriété au wire `getBlock`.
|
||||||
|
|
||||||
|
**SIMD-0096 — Reward full priority fee to validator** est `Activated`, mais modifie la distribution économique sans modifier la forme HTTP consommée par Transport. Aucun calcul de distribution ne doit être réimplémenté côté KSP.
|
||||||
|
|
||||||
|
**SIMD-0550 — Double Disinflation Rate** est en `Review` et annonce explicitement une évolution des valeurs retournées par `getInflationRate` et `getInflationGovernor` sans changement d'API. Les DTOs KSP restent des valeurs runtime et Transport ne réimplémente aucune formule d'inflation.
|
||||||
|
|
||||||
|
### Watchlist obligatoire
|
||||||
|
|
||||||
|
**SIMD-0180 — Vote Account Address Keyed Leader Schedule** est en `Review`. Il demande que les endpoints RPC existants de leader schedule continuent à retourner l'identité validator pour compatibilité et prévoit de nouveaux endpoints vote-account-keyed. Le wrapper `getLeaderSchedule` existant ne change donc pas ; le réaudit final de l'inventaire doit en revanche détecter si de nouveaux endpoints sont devenus officiels.
|
||||||
|
|
||||||
|
**SIMD-0307 — Add Block Footer** est en `Review` et propose une option `footer` ainsi que de nouveaux champs dans `getBlock`. **SIMD-0298 — Add `bank_hash` to block footer** est encore au statut `Idea` et prévoit d'étendre ce footer avec `bank_hash`. Ces éléments sont absents de la baseline stable Agave `v4.2.1`. Ils ne sont donc pas ajoutés maintenant, mais le plan impose un réaudit conjoint avant `getBlock` et à la compliance finale. S'ils deviennent stables pendant `0.2.4`, `KSP-TRANSPORT-007` imposera config, wire et fixtures pour la totalité des champs livrés.
|
||||||
|
|
||||||
|
**SIMD-0490 — Upgrade BPF Stake Program to v5.0.0** est en `Review` et prévoit une évolution du minimum de délégation. `getStakeMinimumDelegation` doit restituer la valeur runtime contextualisée sans coder en dur `1 lamport`, `1 SOL` ou une autre valeur. Réaudit prévu avant la tranche Economics concernée et à la clôture.
|
||||||
|
|
||||||
|
**SIMD-0553 — Base Inclusion and Resource-based Fee** est en `Draft`. Il modifie la sémantique des totals de fee pour `getFeeForMessage`, `simulateTransaction` et `getTransaction.meta.fee` mais n'impose actuellement pas de nouveau JSON wire. Les wrappers acquis restent pass-through/lossless ; la compliance finale réaudite ce point si le schéma stable évolue.
|
||||||
|
|
||||||
|
**SIMD-0123 — Block Revenue Sharing** reste en `Review`. Il peut modifier à terme la provenance/sémantique des rewards sans ajouter aujourd'hui un champ HTTP stable dans `v4.2.1`. KSP ne crée donc aucune taxonomie économique spéculative dans le reward wire.
|
||||||
|
|
||||||
|
## Modifications désormais prévues par le plan
|
||||||
|
|
||||||
|
Les prereleases fonctionnelles devront notamment prévoir :
|
||||||
|
|
||||||
|
```text
|
||||||
|
getBlock
|
||||||
|
confirmed block dédié
|
||||||
|
numRewardPartitions préservé via SolanaWireField<u64> ou équivalent (SIMD-0118)
|
||||||
|
reward de bloc dédié
|
||||||
|
commission nullable
|
||||||
|
commissionBps optionnel/omis (SIMD-0291)
|
||||||
|
transaction version Number(u8) non limitée à 0 (canary SIMD-0385)
|
||||||
|
réaudit conjoint SIMD-0298/0307 avant implémentation finale du contrat
|
||||||
|
|
||||||
|
getInflationReward
|
||||||
|
reward d'inflation distinct du reward de bloc
|
||||||
|
commission nullable
|
||||||
|
commissionBps optionnel/omis (SIMD-0291)
|
||||||
|
|
||||||
|
getStakeMinimumDelegation
|
||||||
|
valeur runtime contextualisée
|
||||||
|
aucun minimum local codé en dur
|
||||||
|
réaudit SIMD-0490
|
||||||
|
|
||||||
|
compliance pre.009
|
||||||
|
réaudit SIMD HTTP au minimum 0180 / 0298 / 0307 / 0385 / 0490 / 0550 / 0553
|
||||||
|
réaudit de l'inventaire officiel pour détecter de nouveaux endpoints
|
||||||
|
vérification qu'aucune évolution devenue stable pendant la session n'est omise
|
||||||
|
```
|
||||||
|
|
||||||
|
Aucune nouvelle dépendance n'est requise par ces décisions.
|
||||||
|
|
||||||
|
## Correction des matrices Markdown
|
||||||
|
|
||||||
|
Les deux matrices du plan ont été réécrites avec les mêmes quatre largeurs de colonnes afin d'être alignées dans la source Markdown.
|
||||||
|
|
||||||
|
Les unions textuelles qui contenaient un pipe interne ont été remplacées par `ou`, notamment :
|
||||||
|
|
||||||
|
```text
|
||||||
|
object ou null
|
||||||
|
array<u64> ou null
|
||||||
|
i64 ou null
|
||||||
|
commission: u8 ou null
|
||||||
|
```
|
||||||
|
|
||||||
|
Le contrôle statique du fichier exige désormais exactement cinq caractères `|` par ligne de tableau : un délimiteur initial, trois séparateurs de colonnes et un délimiteur final. Il n'existe plus de pipe de données à l'intérieur d'une cellule.
|
||||||
|
|
||||||
|
## Version Cargo
|
||||||
|
|
||||||
|
Ce fix est exclusivement documentaire. Conformément à la règle de versioning des fixes documentaires, le signal technique reste :
|
||||||
|
|
||||||
|
```text
|
||||||
|
workspace.package.version = "0.2.4-pre.1"
|
||||||
|
```
|
||||||
|
|
||||||
|
Aucune modification de `Cargo.toml` n'est effectuée.
|
||||||
|
|
||||||
|
## Fichier modifié
|
||||||
|
|
||||||
|
```text
|
||||||
|
docs/plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Le header documentaire du plan passe de `version: 1` à `version: 2`.
|
||||||
|
|
||||||
|
## Fichier ajouté
|
||||||
|
|
||||||
|
```text
|
||||||
|
deltas/0.2.4/pre.001-fix.001.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## Fichiers volontairement inchangés
|
||||||
|
|
||||||
|
```text
|
||||||
|
Cargo.toml
|
||||||
|
CHANGELOG.md
|
||||||
|
ROADMAP.md
|
||||||
|
deltas/0.2.4/pre.001.md
|
||||||
|
crates/ksp-onchain-transport-lib/src/**
|
||||||
|
crates/ksp-onchain-transport-lib/unit_tests/**
|
||||||
|
crates/ksp-onchain-transport-lib/tests/**
|
||||||
|
```
|
||||||
|
|
||||||
|
Les structures/fonctions Rust requises par l'audit sont planifiées pour les tranches fonctionnelles de `0.2.4`; elles ne sont pas introduites artificiellement dans ce fix documentaire d'ouverture.
|
||||||
|
|
||||||
|
## Validations exécutées
|
||||||
|
|
||||||
|
- réaudit primaire du repository SIMD courant et de la baseline Agave stable `v4.2.1` ;
|
||||||
|
- confirmation de SIMD-0118 `Activated` et de son lien avec `numRewardPartitions` ;
|
||||||
|
- confirmation dans Agave `v4.2.1` du champ `UiConfirmedBlock.num_reward_partitions` ;
|
||||||
|
- confirmation dans Agave `v4.2.1` de `Reward.commission_bps` et `RpcInflationReward.commission_bps` ;
|
||||||
|
- confirmation que `RpcVoteAccountInfo.inflation_rewards_commission_bps` est déjà couvert dans KSP `0.2.2` ;
|
||||||
|
- confirmation que `SolanaTransactionVersion::Number(u8)` et les payloads transaction/meta lossless de `0.2.3` n'imposent pas de remédiation SIMD-0385 ;
|
||||||
|
- confirmation que SIMD-0180 est encore `Review`, que les RPC leader schedule existants doivent conserver l'identité validator, et que les futurs endpoints vote-account-keyed relèvent d'une évolution d'inventaire ;
|
||||||
|
- confirmation que SIMD-0186 est `Accepted` et que `loadedAccountsDataSize` est déjà couvert losslessly dans `simulateTransaction` ;
|
||||||
|
- confirmation que SIMD-0298 est encore `Idea`, dépend du block footer de SIMD-0307 et ne justifie aucun champ `bankHash` spéculatif dans la baseline actuelle ;
|
||||||
|
- confirmation que SIMD-0307 est encore `Review` et que ses champs footer sont absents des types stables Agave `v4.2.1` ;
|
||||||
|
- confirmation que SIMD-0490 est encore `Review` et que le wrapper KSP ne doit pas figer une valeur de minimum delegation ;
|
||||||
|
- confirmation que SIMD-0550 est encore `Review` et déclare une évolution de valeurs inflation sans changement d'API ;
|
||||||
|
- confirmation que SIMD-0553 est encore `Draft` et n'impose pas actuellement de nouvelle forme JSON ;
|
||||||
|
- contrôle des deux matrices : quatre colonnes et exactement cinq délimiteurs `|` par ligne ;
|
||||||
|
- contrôle que le delta `pre.001.md` historique reste inchangé.
|
||||||
|
|
||||||
|
## Validations Cargo
|
||||||
|
|
||||||
|
Aucune source Rust, configuration runtime, dépendance ou version Cargo n'est modifiée par ce fix. Les validations Cargo de `pre.001` restent celles à effectuer par l'opérateur avant commit ; ce fix n'en revendique aucune nouvelle.
|
||||||
|
|
||||||
|
## Commit attendu
|
||||||
|
|
||||||
|
Après application et validation documentaire :
|
||||||
|
|
||||||
|
```text
|
||||||
|
v0.2.4-pre.001-fix.001
|
||||||
|
```
|
||||||
|
|
||||||
|
## Suite
|
||||||
|
|
||||||
|
`0.2.4-pre.002` peut démarrer les primitives/configs/results communs en intégrant dès leur conception les exigences SIMD-0118 et SIMD-0291 fixées ci-dessus, avec les watchpoints SIMD explicitement reportés aux tranches concernées.
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md -->
|
<!-- file: docs/plans/011-V0_2_4_HTTP_BLOCKS_ECONOMICS_PLAN.md -->
|
||||||
<!-- version: 1 -->
|
<!-- version: 2 -->
|
||||||
|
|
||||||
# Plan `0.2.4` — HTTP Blocks + Economics + compliance HTTP finale
|
# Plan `0.2.4` — HTTP Blocks + Economics + compliance HTTP finale
|
||||||
|
|
||||||
@@ -83,6 +83,24 @@ https://github.com/anza-xyz/agave/blob/v4.2.1/rpc-client-types/src/config.rs
|
|||||||
https://github.com/anza-xyz/agave/blob/v4.2.1/rpc-client-types/src/response.rs
|
https://github.com/anza-xyz/agave/blob/v4.2.1/rpc-client-types/src/response.rs
|
||||||
```
|
```
|
||||||
|
|
||||||
|
SIMDs primaires ciblés par l'audit `KSP-TRANSPORT-007` :
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0096-reward-collected-priority-fee-in-entirety.md
|
||||||
|
https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0118-partitioned-epoch-reward-distribution.md
|
||||||
|
https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0123-block-revenue-distribution.md
|
||||||
|
https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0180-vote-account-leader-schedule.md
|
||||||
|
https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0185-vote-account-v4.md
|
||||||
|
https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0186-loaded-transaction-data-size-specification.md
|
||||||
|
https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0291-commission-rate-in-basis-points.md
|
||||||
|
https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0298-bank-hash-in-block-footer.md
|
||||||
|
https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0307-add-block-footer.md
|
||||||
|
https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0385-transaction-v1.md
|
||||||
|
https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0490-upgrade-stake-to-v5.md
|
||||||
|
https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0550-double-disinflation.md
|
||||||
|
https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0553-resource-fee-burn.md
|
||||||
|
```
|
||||||
|
|
||||||
## Inventaire officiel réaudité
|
## Inventaire officiel réaudité
|
||||||
|
|
||||||
L'index HTTP Solana actuel contient toujours exactement les catégories suivantes :
|
L'index HTTP Solana actuel contient toujours exactement les catégories suivantes :
|
||||||
@@ -139,25 +157,76 @@ Pour `0.2.4`, cela impose notamment :
|
|||||||
|
|
||||||
- de ne pas réduire `getBlocks` à la seule forme `[start, end, config]` ;
|
- de ne pas réduire `getBlocks` à la seule forme `[start, end, config]` ;
|
||||||
- de conserver le bare encoding legacy de `getBlock` sans le présenter comme forme recommandée ;
|
- de conserver le bare encoding legacy de `getBlock` sans le présenter comme forme recommandée ;
|
||||||
- de préserver `transactionDetails = full | signatures | none | accounts` et les conséquences sur la présence des champs de bloc ;
|
- de préserver `transactionDetails = full ou signatures ou none ou accounts` et les conséquences sur la présence des champs de bloc ;
|
||||||
- de préserver les champs wire riches des transactions/meta/rewards sans importer un client RPC Solana haut niveau ;
|
- de préserver les champs wire riches des transactions/meta/rewards sans importer un client RPC Solana haut niveau ;
|
||||||
- de conserver les `null` positionnels de `getInflationReward` et le champ runtime `commissionBps` lorsqu'il est présent ;
|
- de conserver les `null` positionnels de `getInflationReward` et le champ runtime `commissionBps` lorsqu'il est présent ;
|
||||||
- de ne pas inventer de limite d'adresses `getInflationReward` si aucune limite sémantique fixe n'est établie par la documentation/runtime courant ; la limite générale de taille de requête HTTP n'est pas transformée artificiellement en cardinalité métier KSP.
|
- de ne pas inventer de limite d'adresses `getInflationReward` si aucune limite sémantique fixe n'est établie par la documentation/runtime courant ; la limite générale de taille de requête HTTP n'est pas transformée artificiellement en cardinalité métier KSP.
|
||||||
|
|
||||||
|
## Audit SIMD lié à `KSP-TRANSPORT-007`
|
||||||
|
|
||||||
|
Le statut d'un SIMD n'est pas, à lui seul, le critère d'implémentation de Transport. La règle est la suivante :
|
||||||
|
|
||||||
|
- si la baseline Solana/Agave stable expose déjà un paramètre, un champ ou une variante wire provenant d'une évolution SIMD, KSP doit le préserver même si le document SIMD n'a pas encore le statut `Activated` ;
|
||||||
|
- si un SIMD modifie seulement la sémantique d'une valeur calculée par le runtime sans modifier son wire, KSP ne doit ni recalculer ni figer cette valeur localement ;
|
||||||
|
- si un SIMD `Draft`/`Review` propose une extension RPC absente de la baseline stable retenue, KSP ne l'invente pas mais l'inscrit dans la watchlist et la réaudite avant le wrapper concerné puis à la compliance finale.
|
||||||
|
|
||||||
|
### SIMD applicables à la baseline `v4.2.1`
|
||||||
|
|
||||||
|
**SIMD-0118 — Partitioned Epoch Rewards Distribution** est `Activated` et a un impact direct sur `getBlock`. Le wire stable `UiConfirmedBlock` expose `numRewardPartitions` sous forme optionnelle. La future structure de bloc KSP doit donc :
|
||||||
|
|
||||||
|
- conserver `num_reward_partitions`/`numRewardPartitions` sans synthétiser `0` lorsqu'il est absent ;
|
||||||
|
- utiliser `SolanaWireField<u64>` ou une représentation équivalente capable de préserver au minimum l'omission, et de ne pas écraser un éventuel `null` de compatibilité ;
|
||||||
|
- couvrir par fixture un bloc avec `numRewardPartitions` présent et un bloc où le champ est omis ;
|
||||||
|
- ne pas déduire localement le nombre de partitions à partir des rewards ou de l'epoch.
|
||||||
|
|
||||||
|
**SIMD-0291 — Commission Rate in Basis Points** est encore en `Review`, mais Agave stable `v4.2.1` expose déjà les champs RPC de compatibilité correspondants. Il affecte trois surfaces KSP :
|
||||||
|
|
||||||
|
- `getVoteAccounts.inflationRewardsCommissionBps` : déjà couvert et testé dans la surface `0.2.2`; aucune remédiation n'est requise ;
|
||||||
|
- `getBlock.rewards[].commissionBps` : à couvrir dans `0.2.4` avec un reward wire de bloc dédié, distinct du reward d'inflation ;
|
||||||
|
- `getInflationReward[].commissionBps` : à couvrir dans `0.2.4` dans le DTO `SolanaInflationReward` ou nom final équivalent.
|
||||||
|
|
||||||
|
Pour les deux nouveaux wires de rewards, `commission` reste nullable et `commissionBps` doit préserver son caractère optionnel/omis. Les deux structures ne doivent pas être fusionnées artificiellement : le reward de bloc possède notamment `pubkey`, `lamports`, `postBalance` et `rewardType`, alors que le reward d'inflation possède `epoch`, `effectiveSlot`, `amount` et `postBalance`.
|
||||||
|
|
||||||
|
La surface `getTransaction` de `0.2.3` ne nécessite pas de correction SIMD-0291 : `meta` est déjà conservé losslessly en `SolanaWireField<serde_json::Value>`, ce qui préserve les rewards imbriqués et leurs extensions sans décodage métier.
|
||||||
|
|
||||||
|
### SIMDs déjà absorbés ou sans nouveau wire HTTP
|
||||||
|
|
||||||
|
**SIMD-0185 — Vote Account v4** est `Accepted`. Les nouvelles données de vote account peuvent faire évoluer les sous-arbres retournés par les parsers `jsonParsed`, mais `SolanaParsedAccountData.parsed` reste un `serde_json::Value` lossless. Agave `v4.2.1` n'ajoute pas les collector fields de Vote Account v4 au DTO dédié `RpcVoteAccountInfo`; aucune extension spéculative de `SolanaVoteAccountInfo` n'est donc ajoutée maintenant.
|
||||||
|
|
||||||
|
**SIMD-0186 — Loaded Transaction Data Size Specification** est `Accepted` et précise la sémantique consensus de la taille de données chargées. La surface `simulateTransaction` de `0.2.3` expose déjà `loadedAccountsDataSize` via `SolanaWireField<u32>` et couvre son omission : aucune nouvelle structure n'est requise. Transport ne doit pas recalculer cette valeur à partir des comptes de la transaction ; il restitue le résultat runtime.
|
||||||
|
|
||||||
|
**SIMD-0385 — Transaction V1 Format** est encore en `Review`. Agave `v4.2.1` possède déjà du plumbing V1 dans ses types transaction-status, mais le contrat KSP acquis est volontairement générique : `SolanaTransactionVersion::Number(u8)` n'est pas limité à `0`, et les payloads JSON restent lossless. `0.2.4` doit conserver cette propriété dans `getBlock` et ajouter une canary déterministe avec une version numérique non nulle afin d'interdire une régression vers un modèle `legacy ou v0` seulement.
|
||||||
|
|
||||||
|
**SIMD-0096 — Reward full priority fee to validator** est `Activated`, mais change la distribution économique des priority fees sans changer le wire HTTP que KSP doit décoder. Transport continue à restituer les valeurs runtime ; aucune structure spécifique n'est ajoutée.
|
||||||
|
|
||||||
|
**SIMD-0550 — Double Disinflation Rate** est en `Review` et précise explicitement que `getInflationRate` et `getInflationGovernor` refléteront la nouvelle schedule sans changement d'API. KSP ne doit donc figer ni `initial`, ni `taper`, ni le taux courant : les DTOs restent des valeurs runtime `f64` et aucune formule d'inflation n'est réimplémentée dans Transport. Un réaudit avant la tranche Economics et à la clôture vérifie qu'aucun nouveau champ n'a été ajouté par la baseline stable.
|
||||||
|
|
||||||
|
### Watchlist obligatoire pendant `0.2.4`
|
||||||
|
|
||||||
|
**SIMD-0180 — Vote Account Address Keyed Leader Schedule** est en `Review`. Son volet RPC demande explicitement que les endpoints historiques de leader schedule et slot leader continuent à retourner l'identité validator afin de préserver la compatibilité, tout en prévoyant de nouveaux endpoints vote-account-keyed. Le wrapper KSP `getLeaderSchedule` acquis en `0.2.2` ne doit donc pas être modifié spéculativement. En revanche, le réaudit d'inventaire de `pre.009` doit détecter si de nouveaux endpoints ont rejoint la surface HTTP officielle : ce serait alors une évolution de l'inventaire RPC, pas un changement silencieux du wire de `getLeaderSchedule`.
|
||||||
|
|
||||||
|
**SIMD-0307 — Add Block Footer** est en `Review` et propose précisément une extension de `getBlock` : option de config `footer` et champs footer dans la réponse. Ces éléments sont absents de `RpcBlockConfig` et `UiConfirmedBlock` dans Agave stable `v4.2.1`; ils ne doivent donc pas être inventés dans `pre.002`. **SIMD-0298 — Add `bank_hash` to block footer** est encore au statut `Idea` et prévoit d'étendre ce même footer avec `bank_hash`. Les deux SIMDs doivent être réaudités ensemble au début de la tranche `getBlock` et à `pre.009`. Si une baseline stable expose alors le footer, `KSP-TRANSPORT-007` impose de couvrir toutes ses options et tous ses champs stables, y compris `bankHash` s'il fait partie du wire effectivement livré.
|
||||||
|
|
||||||
|
**SIMD-0490 — Upgrade BPF Stake Program to v5.0.0** est en `Review` et prévoit notamment une hausse du minimum de délégation ainsi que son exposition par le RPC de minimum delegation. Pour `getStakeMinimumDelegation`, KSP doit donc traiter la valeur contextualisée comme une valeur runtime opaque en lamports : aucun minimum `1 lamport`, `1 SOL` ou autre ne doit être codé en dur ou validé côté Transport. Le SIMD sera réaudité avant `pre.007` et à `pre.009`.
|
||||||
|
|
||||||
|
**SIMD-0553 — Base Inclusion and Resource-based Fee** est en `Draft`. Il change la sémantique du total de fees de `getFeeForMessage`, `simulateTransaction` et `getTransaction.meta.fee` sans imposer actuellement de changement de forme JSON. Les wrappers `0.2.3` doivent donc rester pass-through/lossless et ne pas recalculer le fee. La compliance finale `52/52` réauditera cette proposition afin de détecter une éventuelle extension stable de schéma apparue pendant la release.
|
||||||
|
|
||||||
|
Les SIMDs `Review` liés au block-revenue sharing, notamment SIMD-0123, peuvent modifier à terme la provenance/sémantique des rewards, mais n'ajoutent pas de champ HTTP stable dans la baseline `v4.2.1`. Le reward wire de KSP doit donc rester fidèle aux champs effectivement retournés et ne pas encoder une taxonomie économique non présente sur le wire.
|
||||||
|
|
||||||
## Matrice Blocks — 10 wrappers
|
## Matrice Blocks — 10 wrappers
|
||||||
|
|
||||||
| Méthode | Requête à couvrir | Résultat à préserver | Contraintes / décisions `KSP-TRANSPORT-007` |
|
| Méthode | Requête à couvrir | Résultat à préserver | Contraintes / décisions `KSP-TRANSPORT-007` |
|
||||||
|-------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| `getBlock` | `slot`; second paramètre absent, bare encoding legacy, ou config `{commitment, encoding, transactionDetails, maxSupportedTransactionVersion, rewards}` | `object ou null`; `previousBlockhash`, `blockhash`, `parentSlot`, transactions/signatures/rewards selon config, `numRewardPartitions`, `blockTime`, `blockHeight` | commitment runtime au moins `confirmed`; réutiliser les encodings/version/transaction wire de `0.2.3`; préserver omission vs null ; garder les erreurs runtime de bloc/version comme erreurs RPC, sans les masquer |
|
| `getBlock` | `slot`; second paramètre absent, bare encoding legacy, ou config `{commitment, encoding, transactionDetails, maxSupportedTransactionVersion, rewards}` | `object ou null`; `previousBlockhash`, `blockhash`, `parentSlot`, transactions/signatures/rewards selon config, `numRewardPartitions`, `blockTime`, `blockHeight` | commitment runtime au moins `confirmed`; réutiliser les encodings/version/transaction wire de `0.2.3`; préserver omission vs null; `numRewardPartitions` suit SIMD-0118; les rewards préservent `commissionBps` de SIMD-0291; garder les erreurs runtime de bloc/version comme erreurs RPC, sans les masquer |
|
||||||
| `getBlockCommitment` | `slot` uniquement | `{commitment: array<u64> ou null, totalStake: u64}` | aucune config à inventer ; préserver commitment nullable |
|
| `getBlockCommitment` | `slot` uniquement | `{commitment: array<u64> ou null, totalStake: u64}` | aucune config à inventer; préserver commitment nullable |
|
||||||
| `getBlockHeight` | config contextuelle optionnelle `{commitment, minContextSlot}` | `u64` | réutiliser `SolanaContextConfig`; `minContextSlot` est transmis tel quel au runtime |
|
| `getBlockHeight` | config contextuelle optionnelle `{commitment, minContextSlot}` | `u64` | réutiliser `SolanaContextConfig`; `minContextSlot` est transmis tel quel au runtime |
|
||||||
| `getBlockProduction` | config optionnelle `{commitment, identity, range:{firstSlot,lastSlot?}}` | `SolanaRpcResponse<{byIdentity, range}>` | `identity` typée Pubkey ; validation locale déterministe `lastSlot >= firstSlot` lorsque les deux sont fournis ; préserver les couples `[leaderSlots, blocksProduced]` |
|
| `getBlockProduction` | config optionnelle `{commitment, identity, range:{firstSlot,lastSlot?}}` | `SolanaRpcResponse<{byIdentity, range}>` | `identity` typée Pubkey; validation locale déterministe `lastSlot >= firstSlot` lorsque les deux sont fournis; préserver les couples `[leaderSlots, blocksProduced]` |
|
||||||
| `getBlocks` | `[start]`, `[start,end]`, `[start,config]`, `[start,end,config]` | `Vec<u64>` | commitment au moins `confirmed`; conserver l'overload untagged du second paramètre ; `end < start` donne `[]`; rejeter localement une différence `end-start > 500_000` |
|
| `getBlocks` | `[start]`, `[start,end]`, `[start,config]`, `[start,end,config]` | `Vec<u64>` | commitment au moins `confirmed`; conserver l'overload untagged du second paramètre; `end < start` donne `[]`; rejeter localement une différence `end-start > 500_000` |
|
||||||
| `getBlocksWithLimit` | `start`, `limit`, config contextuelle optionnelle | `Vec<u64>` | commitment au moins `confirmed`; `limit <= 500_000`; `limit = 0` est valide et donne `[]` |
|
| `getBlocksWithLimit` | `start`, `limit`, config contextuelle optionnelle | `Vec<u64>` | commitment au moins `confirmed`; `limit <= 500_000`; `limit = 0` est valide et donne `[]` |
|
||||||
| `getBlockTime` | `slot` uniquement | `i64 ou null` | préserver l'absence de timestamp ; les cas cleaned/skipped/not available restent des erreurs RPC runtime, pas des valeurs synthétiques |
|
| `getBlockTime` | `slot` uniquement | `i64 ou null` | préserver l'absence de timestamp; les cas cleaned/skipped/not available restent des erreurs RPC runtime, pas des valeurs synthétiques |
|
||||||
| `getFirstAvailableBlock` | aucun paramètre | `u64` | requête exacte `params: []` ; aucune config |
|
| `getFirstAvailableBlock` | aucun paramètre | `u64` | requête exacte `params: []`; aucune config |
|
||||||
| `getRecentPerformanceSamples` | `limit?` | tableau de `{slot,numTransactions,numSlots,samplePeriodSecs,numNonVoteTransactions?}` | défaut runtime `720`; maximum `720`; rejeter avant I/O `limit > 720`; préserver `numNonVoteTransactions` nullable/ancien runtime |
|
| `getRecentPerformanceSamples` | `limit?` | tableau de `{slot,numTransactions,numSlots,samplePeriodSecs,numNonVoteTransactions?}` | défaut runtime `720`; maximum `720`; rejeter avant I/O `limit > 720`; préserver `numNonVoteTransactions` nullable/ancien runtime |
|
||||||
| `minimumLedgerSlot` | aucun paramètre | `u64` | requête exacte `params: []`; conserver les erreurs ledger/runtime |
|
| `minimumLedgerSlot` | aucun paramètre | `u64` | requête exacte `params: []`; conserver les erreurs ledger/runtime |
|
||||||
|
|
||||||
### `getBlock` — stratégie wire
|
### `getBlock` — stratégie wire
|
||||||
|
|
||||||
@@ -174,17 +243,17 @@ SolanaWireField<T>
|
|||||||
|
|
||||||
`SolanaConfirmedTransaction` ne doit **pas** être réutilisé tel quel pour un élément de bloc : ce DTO contient `slot` et `blockTime`, qui appartiennent au résultat top-level de `getTransaction` et non à chaque élément `transactions[]` d'un bloc. Un type wire de transaction de bloc dédié peut en revanche composer les primitives ci-dessus et préserver `transaction`, `meta` et `version` sans décodage Program.
|
`SolanaConfirmedTransaction` ne doit **pas** être réutilisé tel quel pour un élément de bloc : ce DTO contient `slot` et `blockTime`, qui appartiennent au résultat top-level de `getTransaction` et non à chaque élément `transactions[]` d'un bloc. Un type wire de transaction de bloc dédié peut en revanche composer les primitives ci-dessus et préserver `transaction`, `meta` et `version` sans décodage Program.
|
||||||
|
|
||||||
Les champs top-level dont la présence dépend de la config (`transactions`, `signatures`, `rewards`, `numRewardPartitions`) doivent utiliser une représentation capable de distinguer une omission d'un `null` lorsqu'une telle distinction existe sur le wire. Les transactions `accounts` ne doivent pas être forcées dans une structure `full` plus riche que le wire réellement retourné.
|
Les champs top-level dont la présence dépend de la config (`transactions`, `signatures`, `rewards`, `numRewardPartitions`) doivent utiliser une représentation capable de distinguer une omission d'un `null` lorsqu'une telle distinction existe sur le wire. `numRewardPartitions` est explicitement rattaché à SIMD-0118 et doit être couvert en présent/omis. Le reward wire de bloc doit conserver `commission` nullable et `commissionBps` optionnel/omis de SIMD-0291. Les transactions `accounts` ne doivent pas être forcées dans une structure `full` plus riche que le wire réellement retourné. Une version de transaction numérique différente de `0` doit rester représentable afin de ne pas régresser la compatibilité préparée pour SIMD-0385.
|
||||||
|
|
||||||
## Matrice Economics — 5 wrappers
|
## Matrice Economics — 5 wrappers
|
||||||
|
|
||||||
| Méthode | Requête à couvrir | Résultat à préserver | Contraintes / décisions `KSP-TRANSPORT-007` |
|
| Méthode | Requête à couvrir | Résultat à préserver | Contraintes / décisions `KSP-TRANSPORT-007` |
|
||||||
|---|---|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| `getInflationGovernor` | config commitment optionnelle | `{initial,terminal,taper,foundation,foundationTerm}` en `f64` | réutiliser `SolanaCommitmentConfig`; aucun contexte de réponse |
|
| `getInflationGovernor` | config commitment optionnelle | `{initial,terminal,taper,foundation,foundationTerm}` en `f64` | réutiliser `SolanaCommitmentConfig`; aucun contexte de réponse |
|
||||||
| `getInflationRate` | aucun paramètre | `{total,validator,foundation,epoch}` | requête exacte `params: []` |
|
| `getInflationRate` | aucun paramètre | `{total,validator,foundation,epoch}` | requête exacte `params: []` |
|
||||||
| `getInflationReward` | liste ordonnée d'adresses ; config optionnelle `{epoch,commitment,minContextSlot}` | `Vec<Option<Reward>>` positionnel | ordre/cardinalité identiques aux entrées ; préserver `commission: u8 ou null` **et** `commissionBps: u16` optionnel de Agave `v4.2.1`; aucune limite fixe d'adresses inventée |
|
| `getInflationReward` | liste ordonnée d'adresses; config optionnelle `{epoch,commitment,minContextSlot}` | `Vec<Option<Reward>>` positionnel | ordre/cardinalité identiques aux entrées; préserver `commission: u8 ou null` et `commissionBps: u16` optionnel/omis de Agave `v4.2.1` conformément à SIMD-0291; aucune limite fixe d'adresses inventée |
|
||||||
| `getStakeMinimumDelegation` | config contextuelle optionnelle `{commitment,minContextSlot}` | `SolanaRpcResponse<u64>` | réutiliser `SolanaContextConfig` / `SolanaRpcResponse<T>` |
|
| `getStakeMinimumDelegation` | config contextuelle optionnelle `{commitment,minContextSlot}` | `SolanaRpcResponse<u64>` | réutiliser `SolanaContextConfig` / `SolanaRpcResponse<T>`; restituer la valeur runtime en lamports sans minimum codé en dur; surveiller SIMD-0490 |
|
||||||
| `getSupply` | config optionnelle `{commitment,excludeNonCirculatingAccountsList}` | `SolanaRpcResponse<{total,circulating,nonCirculating,nonCirculatingAccounts}>` | le booléen runtime par défaut est `false`; préserver la liste ordonnée retournée lorsqu'elle est demandée |
|
| `getSupply` | config optionnelle `{commitment,excludeNonCirculatingAccountsList}` | `SolanaRpcResponse<{total,circulating,nonCirculating,nonCirculatingAccounts}>` | le booléen runtime par défaut est `false`; préserver la liste ordonnée retournée lorsqu'elle est demandée |
|
||||||
|
|
||||||
### Extension runtime `commissionBps`
|
### Extension runtime `commissionBps`
|
||||||
|
|
||||||
@@ -194,7 +263,7 @@ La documentation publique actuelle de `getInflationReward` énumère encore uniq
|
|||||||
commission_bps: Option<u16>
|
commission_bps: Option<u16>
|
||||||
```
|
```
|
||||||
|
|
||||||
sérialisé en `commissionBps` lorsqu'il est présent. Ce champ correspond à l'évolution SIMD-0291 et doit être conservé dans le DTO KSP pour ne pas perdre une capacité/extension du runtime stable courant.
|
sérialisé en `commissionBps` lorsqu'il est présent. Ce champ correspond à l'évolution SIMD-0291 et doit être conservé dans le DTO KSP pour ne pas perdre une capacité/extension du runtime stable courant. Le DTO doit préserver séparément `commission` nullable et `commissionBps` optionnel/omis; il ne doit pas convertir les basis points en pourcentage ni dériver l'un des deux champs depuis l'autre.
|
||||||
|
|
||||||
## Contraintes locales retenues
|
## Contraintes locales retenues
|
||||||
|
|
||||||
@@ -238,9 +307,9 @@ Noms définitifs ajustables pendant l'implémentation, responsabilités fixes :
|
|||||||
config getBlock moderne + enum transactionDetails
|
config getBlock moderne + enum transactionDetails
|
||||||
config/range/result getBlockProduction
|
config/range/result getBlockProduction
|
||||||
block commitment result
|
block commitment result
|
||||||
confirmed block + transaction-in-block + reward wire
|
confirmed block + transaction-in-block + reward wire, avec `numRewardPartitions` SIMD-0118 et `commissionBps` SIMD-0291
|
||||||
performance sample
|
performance sample
|
||||||
inflation governor/rate/reward
|
inflation governor/rate/reward, avec reward d'inflation distinct et `commissionBps` SIMD-0291
|
||||||
supply result/config
|
supply result/config
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -306,12 +375,16 @@ Cas de régression obligatoires spécifiques :
|
|||||||
getBlock bare encoding legacy
|
getBlock bare encoding legacy
|
||||||
getBlock transactionDetails full/signatures/none/accounts
|
getBlock transactionDetails full/signatures/none/accounts
|
||||||
getBlock result null
|
getBlock result null
|
||||||
|
getBlock numRewardPartitions présent/omis (SIMD-0118)
|
||||||
|
getBlock rewards commission nullable + commissionBps présent/omis (SIMD-0291)
|
||||||
|
getBlock transaction version numérique non nulle conservée (canary SIMD-0385)
|
||||||
getBlocks [start,config] vs [start,end,config]
|
getBlocks [start,config] vs [start,end,config]
|
||||||
getBlocks range > 500_000 rejetée avant I/O
|
getBlocks range > 500_000 rejetée avant I/O
|
||||||
getBlocksWithLimit 0 et > 500_000
|
getBlocksWithLimit 0 et > 500_000
|
||||||
getRecentPerformanceSamples défaut/720/>720
|
getRecentPerformanceSamples défaut/720/>720
|
||||||
getBlockProduction lastSlot < firstSlot rejeté avant I/O
|
getBlockProduction lastSlot < firstSlot rejeté avant I/O
|
||||||
getInflationReward ordre + null positionnels + commissionBps
|
getInflationReward ordre + null positionnels + commission/commissionBps présent/omis (SIMD-0291)
|
||||||
|
getStakeMinimumDelegation valeur runtime arbitraire sans minimum codé en dur (watch SIMD-0490)
|
||||||
getSupply excludeNonCirculatingAccountsList true/false/omitted
|
getSupply excludeNonCirculatingAccountsList true/false/omitted
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -333,7 +406,7 @@ historical Deprecated/Removed == 14/14
|
|||||||
KSP-TRANSPORT-007 audited current == 52/52
|
KSP-TRANSPORT-007 audited current == 52/52
|
||||||
```
|
```
|
||||||
|
|
||||||
La compliance `KSP-TRANSPORT-007` des 37 wrappers de `0.2.1`–`0.2.3` reste acquise par `docs/validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md`; la clôture `0.2.4` vérifie qu'aucune régression n'a été introduite et applique la même règle aux 15 nouveaux wrappers.
|
La compliance `KSP-TRANSPORT-007` des 37 wrappers de `0.2.1`–`0.2.3` reste acquise par `docs/validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md`; la clôture `0.2.4` vérifie qu'aucune régression n'a été introduite et applique la même règle aux 15 nouveaux wrappers. Le réaudit final inclut explicitement l'état des SIMD susceptibles de modifier la surface HTTP ou sa sémantique observable, au minimum SIMD-0180, SIMD-0298, SIMD-0307, SIMD-0385, SIMD-0490, SIMD-0550 et SIMD-0553, afin qu'une évolution devenue stable pendant la session ne soit pas oubliée. Il réaudite aussi l'inventaire officiel lui-même afin de détecter d'éventuels nouveaux endpoints issus de SIMD-0180 ou d'une autre évolution d'interface.
|
||||||
|
|
||||||
## Smokes live
|
## Smokes live
|
||||||
|
|
||||||
@@ -347,17 +420,20 @@ Le smoke historique Config -> Transport reste une exception transitoire de compo
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
pre.001 audit officiel actuel + Agave stable + matrice + wires + contraintes + sizing
|
pre.001 audit officiel actuel + Agave stable + matrice + wires + contraintes + sizing
|
||||||
pre.002 primitives/configs/results Blocks/Economics partagés + fixtures communes
|
pre.002 primitives/configs/results Blocks/Economics partagés + reward wires SIMD-0118/0291
|
||||||
|
+ fixtures communes
|
||||||
pre.003 Blocks simples : getBlockCommitment, getBlockHeight, getBlockTime,
|
pre.003 Blocks simples : getBlockCommitment, getBlockHeight, getBlockTime,
|
||||||
getFirstAvailableBlock, minimumLedgerSlot
|
getFirstAvailableBlock, minimumLedgerSlot
|
||||||
pre.004 ranges/performance : getBlocks, getBlocksWithLimit, getRecentPerformanceSamples
|
pre.004 ranges/performance : getBlocks, getBlocksWithLimit, getRecentPerformanceSamples
|
||||||
pre.005 getBlockProduction + range/identity/result contextualisé
|
pre.005 getBlockProduction + range/identity/result contextualisé
|
||||||
pre.006 getBlock moderne + bare encoding legacy + transactionDetails + wire bloc riche
|
pre.006 réaudit SIMD-0298/0307 + getBlock moderne + bare encoding legacy + transactionDetails
|
||||||
pre.007 Economics simples : getInflationGovernor, getInflationRate,
|
+ wire bloc riche + SIMD-0118/0291 + canary version numérique SIMD-0385
|
||||||
|
pre.007 réaudit SIMD-0490/0550 + Economics simples : getInflationGovernor, getInflationRate,
|
||||||
getStakeMinimumDelegation, getSupply
|
getStakeMinimumDelegation, getSupply
|
||||||
pre.008 getInflationReward + null positionnels + commissionBps + invariants
|
pre.008 getInflationReward + null positionnels + commissionBps SIMD-0291 + invariants
|
||||||
pre.009 compliance finale 52/52 + 14/14 + KSP-TRANSPORT-007 + docs + smokes + graphes
|
pre.009 réaudit SIMD HTTP (0180/0298/0307/0385/0490/0550/0553 minimum)
|
||||||
+ prompt 0.2.5 — Wallet foundation
|
+ réaudit inventaire officiel + compliance finale 52/52 + 14/14
|
||||||
|
+ KSP-TRANSPORT-007 + docs + smokes + graphes + prompt 0.2.5 — Wallet foundation
|
||||||
rel.001 publication strictement publicationnelle
|
rel.001 publication strictement publicationnelle
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user