Oui, le problème qui persiste est celui dont le symptôme est relevé par @Tortue : le basculement entre branche est buggué (visiblement au niveau du mécanisme qui prévient la double dépense).
A noter que DUP 0.6 pourrait calmer le jeu, mais autant profiter de cette profusion de forks pour renforcer l’algorithme de basculement.
Pareillement, je m’y met dans la journée en espérant identifier la/les erreur(s)
Edit :
J’ai donc trouvé l’origine du problème, liée à l’issue #704 aujourd’hui close.
Explication technique
TLDR;
Les transactions ne s’enchaînent pas correctement dans la blockchain, et créent des situations de fork à chaque nouvelle transaction émise tout en empêchant la résolution de fork de les résorber.
Le protocole spécifie depuis la version 0.3 que les blocs doivent avoir des transactions en version 3, peu importe que le bloc soit en version 4 ou 5.
Cependant, un bug présent jusqu’à la version 0.50.0 (incluse) de Duniter modifiait la valeur du champ Version
de la transaction pour y inscrire la même valeur que le champ Version
du bloc une fois celui-ci ajouté à la base de donnée du nœud. Donc, un nœud avec ce bug propageait des blocs incorrects tandis qu’il recevait un bloc correct.
Cela posait d’abord des problèmes de synchronisation : quand un nouveau bloc était trouvé, celui-ci ne se propageait pas sur le réseau étant donné que le bloc était vu comme invalide.
Sauf que ce bug a également eu un effet pervers par le biais des transactions : les logiciels clients tels Sakia/Cesium ont envoyé des transactions en référençant des transactions précédentes telles que le leur présentaient les nœuds, c’est-à-dire parfois avec une version incorrecte de transaction source. Logiquement, les nœuds auraient dû refuser ces transactions car les sources associées n’auraient jamais dû exister, mais ayant eux-mêmes enregistrés les transactions avec ces versions incorrectes, les sources associées ont existé de fait, et les nœud ont accepté ces transactions.
La blockchain se retrouve donc avec des transactions qui s’enchaînent entre elles via un mécanisme d’empreinte, sauf que celle-ci référence parfois une transaction en version 5, alors qu’une telle transaction n’existe pas (elle existe, mais en version 3).
Ajoutez à cela que le mécanisme de synchronisation initiale ne contrôle pas ni ne force la valeur du champ Version
d’une transaction et l’on obtient un réseau pollué par de faux enregistrements, ce qui contribue très largement à l’apparition de forks d’une part, mais surtout empêche le basculement de branche d’autre part.
Cette situation crée donc des forks, et en plus les empêche de se résorber.
Pour résumer :
- la blockchain est intègre, au sens où les empreintes de blocs sont toutes correctes et l’intégrité des transactions est garantie par leur signature
- le problème vient de la référence qui lie 2 transactions, l’empreinte, qui est calculée avec une version parfois incorrecte
Solution
TLDR;
cgeek va faire une nouvelle version bientôt.
La solution que je retiens évite de revenir sur une partie de la blockchain (plusieurs mois …).
Je vais donc modifier le protocole pour acter le fait qu’un bloc v4 ou v5 peut contenir des transactions consumant des transactions précédentes dont la version diffère de celle signée originellement.
Concrètement quand un bloc passe, si celui-ci contient une transaction TB qui consomme une transaction TA d’un bloc précédent via une empreinte TB->TAv3, alors si la transaction TAv3 n’est pas trouvée, on tente encore 2 autres coups :
- TB->TAv4 (transaction source dont l’empreinte est calculée avec le champ Version: 4)
- TB->TAv5 (transaction source dont l’empreinte est calculée avec le champ Version: 5)
Dès qu’un des coups fonctionne, on s’arrête là. De sorte qu’aucune double dépense n’est possible : c’est juste qu’il existe 3 empreintes possibles menant à la même source.