Audit genesis Ğ1: aucune certification forgeron ne pourra être émise après le bloc genesis

Je poursuis actuellement l’audit de Duniter v2 en urgence, étant donné que la migration définitive a déjà été annoncée pour dans une dizaine de jours. Ce soir, j’ai identifié un nouveau problème.

Dans l’état actuel du genesis, aucune certification forgeron ne pourra être émise après le bloc genesis.

Conséquence directe : aucun nouveau forgeron ne pourra jamais entrer dans la toile des forgerons.

Explication du bug

Voici ce qui se passe techniquement :

  • Lors de la génération du genesis, les 15 smiths initiaux sont organisés en « clique » : chacun certifie tous les autres.
  • Cela signifie que chaque smith reçoit 14 certifications (une de chacun des 14 autres).

Le problème vient d’une règle appelée SmithMaxByIssuer :

  • Cette règle limite le nombre maximum de certifications qu’un smith peut émettre.
  • Or, la construction du genesis ne vérifie pas cette limite (elle interdit seulement l’auto-certification).
  • En revanche, dès le bloc 1, l’appel runtime certify_smith applique strictement la condition issued_certs < SmithMaxByIssuer

Résultat :

Les forgerons du genesis ont déjà dépassé la limite autorisée (SmithMaxByIssuer = 12)
Donc à partir du bloc 1, ils ne peuvent plus émettre la moindre certification supplémentaire.

:right_arrow: Aucune nouvelle certification possible.
:right_arrow: Aucun nouveau smith ne pourra être ajouté.
:right_arrow: Le système est verrouillé dès le départ.

Solutions envisagées

Mon plan initial (il y a 8 mois)

Mon idée à l’époque n’était pas de générer automatiquement une clique complète, mais de construire manuellement une toile initiale de forgerons, où chacun déclarerait explicitement qui il souhaite certifier.

La trace de cette intention est visible ici :

Malheureusement, j’ai eu des problèmes de santé peu après, ce qui m’a empêché de mettre ce processus en place. Aujourd’hui, avec la migration imminente, nous n’avons plus le temps d’implémenter une telle procédure proprement.

Proposition alternative (rapide et pragmatique)

Modifier l’algorithme de génération des données de genesis :

Au lieu que chaque forgeron reçoive 14 certifications (une de chacun des autres), chaque forgeron recevrait seulement 3 certifications réparties au hasard.

Cela permettrait :

  • De respecter la limite SmithMaxByIssuer
  • De laisser de la capacité d’émission de certifications après le bloc 0
  • D’éviter le blocage définitif du système
  • De corriger le problème sans refonte complète du process de genesis

Issue gitlab: g1 Genesis State Prevents New Smiths After Genesis (#348) · Issues · nodes / rust / Duniter v2S · GitLab

7 Likes

Voici un script Python qui génère une toile aléatoire où chacun a exactement 3 certifications émises et 3 certifications reçues. (remplacer la liste par la liste des smiths)

import random

def generate(smiths, n=3):
        certs = []
        issuers = []
        recipients = []
        # Fill the bags
        for smith in smiths:
                issuers += [smith] * n
                recipients += [smith] * n
        # While the bags are not empty
        while len(issuers) > 0:
                # Pick one identity in each bag
                issuer = random.randint(0, len(issuers)-1)
                recipient = random.randint(0, len(issuers)-1)
                # If they are not the same
                if issuers[issuer] == recipients[recipient]:
                        continue
                # If they are not already an edge
                if (issuers[issuer], recipients[recipient]) in certs:
                        continue
                # Remove them from the bags
                certs.append((issuers.pop(issuer), recipients.pop(recipient)))
        return certs

print(generate([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]))

Pourquoi ce problème ne s’est pas produit en gtest ?

Trop peu de smiths dans la clique.

1 Like

Non, même avec le même nombre de smiths dans la clique, ça n’aurait pas été détecté, car en gtest: SmithMaxByIssuer = 100.

2 Likes

Oui j’ai répondu un peu vite, en regardant l’historique Git on avait une clique de 13.

Tu as raison c’est ce stock de 100.

1 Like

J’ai exploré cette solution : elle demande des changements de code un peu complexes et risqués, tout en ne respectant plus la signification de « clique ».

Je propose une approche plus simple et moins risquée : déclarer explicitement dans g1.yaml l’état exact de la toile forgeron initiale. C’est en effet supporté dans le code ; j’ai ajouté un test pour m’en assurer. Voici une MR GitLab qui déclare une toile forgeron initiale à la main avec les certifs reçus par chacun :

@cgeek, @tuxmain, @poka, pouvez-vous la reviewer ?

2 Likes

C’est ok pour moi!
Comment as-tu généré ce set se certification smiths ? A la main ou via un algo ?
Je vais ajouter cette génération de format automatiquement dans duniter-mocks.

1 Like