J’ai regardé ta branche distance
, effectivement il y a déjà pas mal d’éléments. Personnellement je préfère te laisser faire cette partie si tu as envie de la réaliser, sinon je m’y investirai mais plus tard (plutôt après la migration pour l’instant).
Les éléments essentiels sont prêts. Voici un résumé chronologique du fonctionnement :
- L’identité est créée, confirmée, certifiée. Elle ne peut pas encore être validée.
- Quelqu’un demande par un extrinsic l’évaluation de sa règle de distance. L’identité est alors ajoutée dans un des 3 pools d’évaluation, qui tournent à chaque session.
- À la session suivante, les oracles récupèrent le pool par RPC, calculent et enregistrent le résultat (pour toutes les identités dans le pool) dans un fichier.
- À la session suivante, Duniter récupère ce fichier en local s’il existe, et le publie en inhérent quand il écrit un bloc. À chaque publication on calcule la médiane des résultats publiés dans la session et on met à jour le storage.
- Au début de la session suivante, on ajoute chaque identité ayant un résultat positif (règle de distance respectée) dans une table du storage.
- Lors de la validation ou du renouvellement d’une identité, on vérifie que l’identité est bien dans la table des résultats positifs.
L’oracle est un exécutable indépendant, qui peut être lancé par cron par exemple à chaque demi-heure.
Le fonctionnement par fichier plutôt que par sémaphore ou thread permet une plus grande flexibilité et une plus grande résilience aux pannes (le nœud ou l’oracle peuvent planter et redémarrer sans perte de données).
TODO :
- Faire marcher les tests end2end. En mode manual seal, les inhérents sont bien fournis par les providers mais les extrinsics correspondants ne sont pas créés.
- Benchmark. Peut-être qu’il serait intéressant d’étaler sur plusieurs blocs l’application des résultats et la mise à jour des médianes, même si ces algos sont au pire en temps linéaire en le nombre d’identités à tester.
- Antispam. Le poids blockchain étant assez faible, il faut empêcher le spam autrement. Demande d’évaluation autorisée uniquement aux identités confirmées et certifiées mais non validées, ou validées mais expirant bientôt, par exemple.
- Offences. Un évaluateur qui envoie plusieurs fois son résultat devrait être puni.
- Supprimer les anciens fichiers d’évaluation.
Questions :
- Qui peut demander l’évaluation de la règle de distance ? (tout le monde, un membre, l’identité concernée)
- Quand oublie-t-on le résultat positif d’une évaluation ? (délai fixe après publication, lors de la validation)
- Si aucun oracle n’a parlé, est-ce que l’identité est par défaut validée ou invalidée ?
- Une évaluation négative annule-t-elle une évaluation positive passée ?
Que se passe-t-il pour les identités qui ne satisfont pas à la règle de distance ?
Rien, elles se verront refuser validate_identity et renew_membership.
Une évaluation négative n’annule pas une évaluation positive précédente. Mais on peut encore décider que si.
Pourquoi ne pas justement mettre un poids élevé, de l’ordre de celui qui serait s’il n’y avait pas d’oracle ?
Implicitement ma question portait sur les certifications associées. Restent-elles valides ? Que peux faire le candidat membre pour améliorer les choses ?
La distance n’est vérifiée que dans la validation et le renouvellement des identités, mais n’a aucun impact sur les certifications. Les identités et certifications préexistantes seront indemnes. Il faudra juste penser à demander l’évaluation de la distance avant de renouveler l’identité.
Proposition d’antispam pour la demande d’évaluation de la règle de distance :
pour chaque demande d’évaluation, on dispose de :
- idty_index de l’identité demandeuse soumise à évaluation (minimum 5 certif reçues)
- statut parmi ( inexistant, en attente, positive, négative)
pour pouvoir soumettre une demande d’évaluation il faut que le statut soit inexistant (absence de demande existante) ou “ négative”.
une évaluation positive est valide pendant un délai défini (1 mois par exemple), après cela, l’expiration programmée la supprime
Voici les transitions possibles :
- [ absence de demande] — demande —> [ statut “en attente”]
- — évaluation —> [ statut “négative”]
- — demande —> [ statut “en attente”]
- — évaluation —> [ statut “positive” (expiration programmée)]
- — validation / renouvellement —> [ absence de demande]
- — expiration —> [ absence de demande]
- — évaluation —> [ statut “négative”]
Donc au maximum, une identité peut cycler un renouvellement d’identité toutes les deux sessions, ce qui me semble largement acceptable.
Ça répond donc aux
- Qui peut demander l’évaluation de la règle de distance ? (tout le monde, un membre, l’identité concernée)
→ seulement l’identité concernée - Quand oublie-t-on le résultat positif d’une évaluation ? (délai fixe après publication, lors de la validation)
→ lors de la validation si elle a lieu avant le délai fixe - Si aucun oracle n’a parlé, est-ce que l’identité est par défaut validée ou invalidée ?
→ le statut reste “en attente”, donc pas de validation possible - Une évaluation négative annule-t-elle une évaluation positive passée ?
→ il ne peut pas y avoir d’évaluation négative suite à une évaluation positive
Et il me semble que ça répond aussi à l’antispam.
Ok donc je représenterais ces états d’identités par une map DistanceStatus :
- inexistant ou négatif → absence (car il est inutile de conserver un résultat négatif)
- en évaluation → variante Pending
- positif → variante Valid
Il suffit alors de vérifier l’absence de l’identité dans la map.
Une autre map sera nécessaire pour indexer les blocs (ou plutôt les sessions) d’expiration.
C’est la solution évidente, puisque la médiane des résultats n’existe pas (cependant ce n’est pas l’oracle qui déclenche l’application des résultats, et décider d’un résultat positif serait possible sans coût supplémentaire), mais ça ne répond pas à la question sur la résilience. Est-ce qu’on veut qu’une pénurie d’oracles empêche la TdC de fonctionner, ou au contraire qu’elle permette de contourner la règle de distance.
Finalement avec l’hypothèse que les pénuries d’oracles seront rares et courtes, je pense qu’il est préférable de faire patienter quelques membres et futurs membres honnêtes plutôt que de laisser des opportunités même très courtes à des attaquants.
Je réitère : pourquoi ne pas mettre un poids élevé à l’extrinsic de demande d’évaluation ? Du moins des frais élevés à proportion de ce que l’extrinsic représenterait en terme de poids si celui-ci était sans oracle.
Si j’ai bien lu, rien n’empêche un membre de spammer sa demande.
Et les lui rembourser si sa demande s’évalue positivement par la suite.
On peut bloquer (en reserved ou frozen, je ne sais plus lequel) un montant sur le compte. En cas d’évaluation positive ou d’absence d’oracle on le débloque ; négative on le transfère à la trésorerie.
D’accord mais il faut aussi que ce montant soit directement décompté si l’extrinsic échoue lui-même (ex. si demande d’évaluation alors qu’il en a déjà une en attente).
Et mettre ce montant en proportion du coût CPU car l’oracle a tout de même un impact sur la machine au cas où l’extrinsic passe.
Ce montant serait indépendant et complémentaire des poids, donc l’extrinsic coûterait toujours son poids, et le blocage de montant ne serait utile qu’en cas de calcul effectif.
Pour la proportion au coût CPU ça va être compliqué, puisque ça dépend de la TdC. On peut benchmarker l’oracle, et on fait un ajustement après l’évaluation en fonction du coût réel, mais comme ce n’est pas aussi critique que le remplissage des blocs (cette ressource étant plus flexible) je pense qu’on peut se contenter d’un coût antispam fixe.
Oui aucun soucis avec ça.
Mais le remplissage des blocs est justement basé sur une évaluation faite à CPU disponible : donc si l’oracle tourne en parallèle, il affecte aussi par interférence le client Duniter et rend potentiellement tous les poids des extrinsics incorrects dans les faits.
Mettre des frais proportionnels (à réévaluer régulièrement) me semble logique de ce point de vue.
Pas forcément puisque le runtime est monocœur. L’oracle peut être configuré pour laisser par exemple deux cœurs, ou bien avoir une priorité moindre.
De plus les benchmarks sont faits pour la plus petite machine attendue, donc toute machine plus puissante aura du temps libre.
Voilà l’argument qu’il me fallait. Et il suffit de mettre dans notre machine de référence d’avoir au moins 4 cœurs.
C’est bon pour moi
J’ai relu le topic en entier, pour comprendre d’où venait le code de la branche distance
que produit tuxmain.
Je note que l’on est encore parti sur une solution dont on n’avait pas besoin, il y avait les offchain workers qui mâchaient le travail, mais non, nous sommes partis sur un binaire dédié tout ça pour une optimisation à base de GPU et SIMD dont on a franchement rien à faire pour 8000 membres.
En plus, pile au moment où j’avais du code prêt pour faire directement le calcul onchain permettant de couvrir le besoin pour encore moins cher que l’offchain worker.
Bref je vais arrêter de passer du temps sur cette partie du boulot, je te laisse faire @tuxmain car ça semble te tenir à cœur.
Mais par pitié, arrêtons avec cette early optimisation qui nous coûte si cher.
Il était question d’optimisations avec GPU et SIMD uniquement pour la version matricielle, qu’on a écartée.
J’ai continué l’oracle même une fois que ta solution onchain était prête car elle n’allait peut-être pas suffire longtemps.
Je n’ai pas utilisé d’offchain worker parce que j’ai suivi l’idée d’Élois, qui était même plus compliquée que nécessaire (pas besoin d’appels RPC). Cependant ce qui m’a pris beaucoup de temps n’était pas la logique, mais de comprendre comment utiliser Substrate. Implémenter un offchain worker aurait demandé de creuser un concept Substrate de plus. C’est toujours faisable, et ça simplifierait probablement l’installation pour les forgerons.
On peut aussi partir sur la solution onchain et aviser après la migration, mais ça sera aussi beaucoup de boulot de retirer/remplacer toute la complexité apportée pour changer de système, donc je ne suis pas sûr que ce soit un gain de temps.
Personnellement je n’ai pour l’instant regardé de près aucune de deux solutions. Je ne suis pas fan du fait d’intégrer la règle de distance à la pallet certification plutôt que de l’avoir dans une pallet à part, mais d’un point de vue de gestion du projet, je suis totalement prêt à assumer une complexité additionnelle du moment qu’elle est reportée à après la migration.
Les solutions proposées par elois sont souvent sur-ingéniérées et immatures. C’est le cas du random id et de la sous-toile forgeron (à mon avis). Je cherche à simplifier sans tout ré-écrire pour sortir une version en production et reporter la ré-écriture à plus tard (je me ferais un plaisir de le faire, mais ce n’est vraiment pas le moment).
Pour savoir ce qu’on va faire pour la règle de distance, ce serait bien d’en discuter tous les trois ensemble. Quelles sont tes dispo en ce moment @tuxmain ?
Je suis dispo en journée du lundi au vendredi, et tous les soirs.