# Intégrer la règle de distance au Runtime

**URL:** https://forum.duniter.org/t/integrer-la-regle-de-distance-au-runtime/13137
**Category:** R&D
**Tags:** oracle, distance
**Created:** [17 June 2025 17:09 UTC](https://forum.duniter.org/t/integrer-la-regle-de-distance-au-runtime/13137 "2025-06-17T17:09:40Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![cgeek](https://forum.duniter.org/user_avatar/forum.duniter.org/cgeek/32/279_2.png) [@cgeek](https://forum.duniter.org/u/cgeek)
#### Post date: [17 June 2025 17:09 UTC](https://forum.duniter.org/t/integrer-la-regle-de-distance-au-runtime/13137/1 "2025-06-17T17:09:40Z")

</div>

Je viens seulement d’y penser, mais le fait que la règle de distance soit implémentée via Oracle empêche aussi sa mise à jour de façon fluide sur la blockchain. En gros : à chaque changement de règle de WoT, nous allons devoir organiser une grande messe de mise à jour du Client Duniter.

Or nous avons [beaucoup d’idées potentielles](https://forum.duniter.org/t/liens-faibles-intermediaires-forts/4627), et le passage à Substrate a été motivé en grande partie _pour la facilité des mises à jour_ : se prendre les pieds dans le tapis concernant les règles de distance de la WoT est quand même dommage.

C’est pour cela que je me demande à quel point nous ne pourrions pas _rapatrier les règles dans le Runtime_.

Je poste ce sujet pour la réflexion. Néanmoins je serai un peu chagriné de devoir lancer la V2 et savoir d’avance qu’il faudra mettre à jour le Client pour faire évoluer cette partie.

Quelques réflexions en vrac :

- on pourrait conserver l’Oracle, mais faire exécuter à celui-ci un code stocké dans le Storage (un WASM par exemple) plutôt qu’un code hardcodé dans le Client ;
- le calcul de distance pourrait-il être découpé en plusieurs étapes ? Si oui, alors on pourrait garder son exécution directement en blockchain, avec une exécution progressive et stockage des résultats intermédiaires.

---

<div class="post-metadata">

### Author: ![HugoTrentesaux](https://forum.duniter.org/user_avatar/forum.duniter.org/hugotrentesaux/32/6396_2.png) [@HugoTrentesaux](https://forum.duniter.org/u/HugoTrentesaux)
#### Post date: [20 June 2025 17:26 UTC](https://forum.duniter.org/t/integrer-la-regle-de-distance-au-runtime/13137/2 "2025-06-20T17:26:49Z")

</div>

Moi aussi la complexité amenée par l’oracle me chagrine.

Ce que tu dis ressemble à ce que elois proposait en réponse à ton message :

> [@Calcul de distance via oracle](https://forum.duniter.org/t/calcul-de-distance-via-oracle/9012/4):
>
> C’est pour cela que substrate a mis en place la notion de “offchain workers”, c’est du code qui est dans le runtime (donc protocolaire), mais exécuté off-chain

Tuxmain aussi y a réfléchi :

> [@Besoin de plus de forgeron avec oracle de distance!](https://forum.duniter.org/t/besoin-de-plus-de-forgeron-avec-oracle-de-distance/12669/15):
>
> Peut-être même qu’en utilisant le mécanisme d’offchain worker de Substrate on peut se passer de RPC.

Il y a aussi le ticket [!293](https://git.duniter.org/nodes/rust/duniter-v2s/-/issues/293) mais il ne décrit pas précisément la suggestion.

---

<div class="post-metadata">

### Author: ![cgeek](https://forum.duniter.org/user_avatar/forum.duniter.org/cgeek/32/279_2.png) [@cgeek](https://forum.duniter.org/u/cgeek)
#### Post date: [20 June 2025 17:32 UTC](https://forum.duniter.org/t/integrer-la-regle-de-distance-au-runtime/13137/3 "2025-06-20T17:32:51Z")

</div>

Excellent, merci ! C’est typiquement le genre d’infos qui me manquait.

Pour l’instant j’explore une autre piste, mais sinon l’offchain worker correspond tout à fait.

---

<div class="post-metadata">

### Author: ![elois](https://forum.duniter.org/user_avatar/forum.duniter.org/elois/32/1541_2.png) [@elois](https://forum.duniter.org/u/elois)
#### Post date: [27 June 2025 14:35 UTC](https://forum.duniter.org/t/integrer-la-regle-de-distance-au-runtime/13137/4 "2025-06-27T14:35:22Z")

</div>

En pratique, les « offchain workers » ne sont pas très fiables ni pratiques : ils sont lancés après chaque bloc et obligent à gérer manuellement les forks.

Si l’on veut intégrer la logique de la règle de distance dans le runtime, la solution la plus adaptée est de créer une runtime API. Une runtime API, c’est une fonction définie dans le runtime que le client peut appeler hors chaîne, tout en ayant un accès lecture au storage.

Je suggère de créer une tâche côté client qui appelle deux API runtime :  
1. Une première API `distance_computable` qui vérifie s’il y a une évaluation à faire et qui contrôle si l’une des clés publiques enregistrées pour le calcul de distance figure dans le keystore du nœud.  
2. Une deuxième API `distance_compute` qui calcule effectivement la distance.

L’appel d’une runtime API nécessite d’être un full node, mais présente plusieurs avantages :  
• Un unique binaire, sans option de configuration supplémentaire : si l’opérateur souhaite calculer la distance, il lui suffit d’insérer une clé privée dans le keystore du nœud et d’enregistrer la clé publique on-chain comme « calculateur de distance ». Le nœud se met automatiquement à calculer la distance dès qu’il est autorisé à le faire.  
• Plus besoin de transférer des données vers un composant externe chargé du calcul : le code de distance accède directement au storage on-chain, sans contrainte de durée.

Nous utilisons un mécanisme similaire dans Moonbeam pour déterminer si un nœud doit produire un bloc : la fonction `first_eligible_key` récupère toutes les clés du keystore associées à un `KeyId` donné (4 octets arbitraires) et, pour chacune, appelle la runtime API `can_author` afin de vérifier si la clé publique (`NimbusId`) est enregistrée comme autorité et éligible pour le prochain bloc :

> <https://github.com/Moonsong-Labs/moonkit/blob/moonbeam-polkadot-stable2412/client/consensus/nimbus-consensus/src/lib.rs#L188>

Cela nous a permis de modifier l’algorithme d’éligibilité sans mettre à jour le client. Je propose d’appliquer la même approche dans duniter-v2s pour décider dynamiquement si le nœud doit évaluer la distance ou non.

Il suffit de définir des runtimes API dans la pallet distance puis de les mapper dans ce fichier:

> **[runtime/common/src/apis.rs · master · nodes / rust / Duniter v2S · GitLab](https://git.duniter.org/nodes/rust/duniter-v2s/-/blob/master/runtime/common/src/apis.rs)**
>
> Duniter v2 based on Substrate framework doc: https://doc-duniter-org.ipns.pagu.re/duniter/index.html

---

<div class="post-metadata">

### Author: ![cgeek](https://forum.duniter.org/user_avatar/forum.duniter.org/cgeek/32/279_2.png) [@cgeek](https://forum.duniter.org/u/cgeek)
#### Post date: [27 June 2025 16:54 UTC](https://forum.duniter.org/t/integrer-la-regle-de-distance-au-runtime/13137/5 "2025-06-27T16:54:13Z")

</div>

> [@elois](#):
>
> Une deuxième API `distance_compute` qui calcule effectivement la distance.

Ah super ! En fait il ne nous manque que cela. On peut conserver l’oracle tel qu’on l’a, ça ne me dérange pas. Tout ce qu’il faut c’est que le code de calcul soit dans le Runtime.

Ce sera probablement la solution la plus simple et moins coûteuse, je persiste un peu dans l’autre solution que je voulais explorer, mais probablement qu’on va partir sur ta solution avec la 2ème API 🙂

Merci du petit message !

---

<div class="post-metadata">

### Author: ![elois](https://forum.duniter.org/user_avatar/forum.duniter.org/elois/32/1541_2.png) [@elois](https://forum.duniter.org/u/elois)
#### Post date: [29 June 2025 14:17 UTC](https://forum.duniter.org/t/integrer-la-regle-de-distance-au-runtime/13137/6 "2025-06-29T14:17:30Z")

</div>

> [@cgeek](#):
>
> On peut conserver l’oracle tel qu’on l’a, ça ne me dérange pas.

Moi si : le fait d’avoir un binaire séparé me gêne autant côté opérateur que côté développeur :

- Côté opérateur, je ne participe pas au calcul de distance pour cette raison (je ne veux pas gérer plusieurs binaires/images pour mon nœud Duniter).

- Côté développeur, ça complique le workflow dès qu’on réalise un changement de code qui impacte les métadonnées du runtime, car le binaire duniter-oracle utilise Subxt et ne compile plus si on modifie ces métadonnées. Pour la MR [!328](https://git.duniter.org/nodes/rust/duniter-v2s/-/merge_requests/328), par exemple, j’ai dû commenter toutes les occurrences de « duniter-oracle » pour pouvoir compiler mes changements et générer les nouvelles métadonnées.

C’est pour ça que j’avais créée [l’issue #293](https://git.duniter.org/nodes/rust/duniter-v2s/-/issues/293).

Ce serait chouette si tu pouvais profiter des changements sur lesquels tu travailles pour fusionner l’oracle dans le binaire duniter-v2s ; sinon, je pourrais peut-être m’en charger moi-même plus tard 🙂

---

<div class="post-metadata">

### Author: ![tuxmain](https://forum.duniter.org/user_avatar/forum.duniter.org/tuxmain/32/6423_2.png) [@tuxmain](https://forum.duniter.org/u/tuxmain)
#### Post date: [29 June 2025 14:23 UTC](https://forum.duniter.org/t/integrer-la-regle-de-distance-au-runtime/13137/7 "2025-06-29T14:23:59Z")

</div>

Je rappelle qu’il n’y a plus besoin de binaire séparé, l’oracle est une sous-commande du client. Je ne sais pas ce qui a été fait côté Docker.

L’oracle n’est pas intégré au client pour autant, il reste dans un processus séparé et lancé indépendamment, et je suis d’accord que ça pose des problèmes.

Edit: pour le problème de générer les métadonnées, il y a une feature cargo qu’on peut désactiver.

---

<div class="post-metadata">

### Author: ![cgeek](https://forum.duniter.org/user_avatar/forum.duniter.org/cgeek/32/279_2.png) [@cgeek](https://forum.duniter.org/u/cgeek)
#### Post date: [29 June 2025 14:43 UTC](https://forum.duniter.org/t/integrer-la-regle-de-distance-au-runtime/13137/8 "2025-06-29T14:43:13Z")

</div>

Ok je comprends. Cela me prendra sûrement du temps néanmoins : la difficulté principale que j’y vois est de trouver les créneaux de calcul pour éviter d’impacter l’import de blocs. C’est pour cette raison qu’il avait été choisi d’avoir un binaire/processus séparé il me semble.

---

<div class="post-metadata">

### Author: ![elois](https://forum.duniter.org/user_avatar/forum.duniter.org/elois/32/1541_2.png) [@elois](https://forum.duniter.org/u/elois)
#### Post date: [29 June 2025 14:53 UTC](https://forum.duniter.org/t/integrer-la-regle-de-distance-au-runtime/13137/9 "2025-06-29T14:53:18Z")

</div>

> [@cgeek](#):
>
> la difficulté principale que j’y vois est de trouver les créneaux de calcul pour éviter d’impacter l’import de blocs

La bonne pratique consiste à créer une tâche cliente asynchrone qui s’abonne aux notifications de finalisation des blocs, et à laisser Tokio gérer les ressources.

De plus, si l’on utilise une runtime API, le calcul de distance sera nécessairement mono-cœur : c’est plus lent, mais cela garantit que les autres cœurs du CPU restent disponibles pour l’importation des blocs (qui elle aussi est mono-cœur).

EDIT: J’ai ajouté un commentaire au [ticket #293](https://git.duniter.org/nodes/rust/duniter-v2s/-/issues/293) où j’essaie de synthétiser ce qui semble se dégager de cette discussion.

---

<div class="post-metadata">

### Author: ![cgeek](https://forum.duniter.org/user_avatar/forum.duniter.org/cgeek/32/279_2.png) [@cgeek](https://forum.duniter.org/u/cgeek)
#### Post date: [29 June 2025 20:08 UTC](https://forum.duniter.org/t/integrer-la-regle-de-distance-au-runtime/13137/10 "2025-06-29T20:08:14Z")

</div>

Ok merci pour l’info pratique, et à y réfléchir, avec le calcul dans le Runtime il semble assez évident qu’il s’agit d’une tâche principalement I/O. Donc effectivement Tokio saura parfaitement optimiser les ressources et il ne devrait pas y avoir d’impact sensible pour l’instant avec moins de 10k membres.

Par contre il serait bon de monitorer un peu le calcul pour se rendre compte de son impact futur.

---

<div class="post-metadata">

### Author: ![tuxmain](https://forum.duniter.org/user_avatar/forum.duniter.org/tuxmain/32/6423_2.png) [@tuxmain](https://forum.duniter.org/u/tuxmain)
#### Post date: [29 June 2025 20:40 UTC](https://forum.duniter.org/t/integrer-la-regle-de-distance-au-runtime/13137/11 "2025-06-29T20:40:08Z")

</div>

Il y a un test (désactivé par défaut, je crois qu’il faut faire `--include-ignored` ou quelque chose comme ça pour le lancer) qui benchmark le calcul sur la totalité des membres. Il faudrait le compiler en WASM pour évaluer la perte de perf. D’après des benchmarks Rust natif vs Rust WASM trouvés sur Internet, ça pourrait faire ×4 ou ×5, ce qui reste assez rapide.

---

<div class="post-metadata">

### Author: ![elois](https://forum.duniter.org/user_avatar/forum.duniter.org/elois/32/1541_2.png) [@elois](https://forum.duniter.org/u/elois)
#### Post date: [30 June 2025 12:16 UTC](https://forum.duniter.org/t/integrer-la-regle-de-distance-au-runtime/13137/12 "2025-06-30T12:16:29Z")

</div>

> [@cgeek](#):
>
> Tokio

J’ai parlé de Tokio car c’est ce que Substrate utilise sous le capot ; tu n’as pas besoin d’utiliser Tokio directement.  
Cette [présentation au Sub0 2022](https://www.youtube.com/watch?v=iKqdXNo0OH4) montre comment créer un Substrate worker async qui s’abonne aux blocs finalisés. Ils expliquent aussi comment soumettre une transaction on-chain depuis le worker pour « publier » le résultat. Dans leur exemple, la logique métier est implémentée en natif côté client, mais rien n’empêche le worker d’appeler une runtime API à la place.

> [@cgeek](#):
>
> il serait bon de monitorer un peu le calcul pour se rendre compte de son impact futur.

> [@tuxmain](#):
>
> Il y a un test (…) qui benchmark le calcul sur la totalité des membres. Il faudrait le compiler en WASM pour évaluer la perte de perf

Le mieux serait plutôt de créer un benchmark dans le pallet distance, car les benchmarks de pallet compilent déjà en WASM. On peut très bien benchmarker des fonctions publiques du pallet même si ce ne sont pas des “call”.

> [@tuxmain](#):
>
> D’après des benchmarks Rust natif vs Rust WASM trouvés sur Internet, ça pourrait faire ×4 ou ×5, ce qui reste assez rapide.

Substrate effectue une compilation JIT Wasm-to-native au démarrage du nœud et après chaque mise à jour du runtime. Ce type de compilation n’est pas aussi optimisé que ce que fait `rustc`, mais il permet d’obtenir des performances proches du natif.

---

<div class="post-metadata">

### Author: ![cgeek](https://forum.duniter.org/user_avatar/forum.duniter.org/cgeek/32/279_2.png) [@cgeek](https://forum.duniter.org/u/cgeek)
#### Post date: [16 September 2025 15:54 UTC](https://forum.duniter.org/t/integrer-la-regle-de-distance-au-runtime/13137/13 "2025-09-16T15:54:51Z")

</div>

A post was merged into an existing topic: [Jooam toujours en attente malgré 5 certifications OK](https://forum.duniter.org/t/jooam-toujours-en-attente-malgre-5-certifications-ok/13294/14)

---

<div class="post-metadata">

### Author: ![cgeek](https://forum.duniter.org/user_avatar/forum.duniter.org/cgeek/32/279_2.png) [@cgeek](https://forum.duniter.org/u/cgeek)
#### Post date: [16 September 2025 15:52 UTC](https://forum.duniter.org/t/integrer-la-regle-de-distance-au-runtime/13137/14 "2025-09-16T15:52:37Z")

</div>

Sauf surprise, on va rester sur le fonctionnement actuel. On migrera vers une version basée sur le Runtime plus tard, nécessitant une migration du client. Tant pis, ce ne devrait pas être compliqué.
