Salut tout le monde.
Dans le cadre de fyyg j’ai cherché de nouveaux algorithmes de consensus basé sur un ensemble d’identité uniques (ce que produit la toile de confiance), et une proposition me semble tout à fait utilisable sur Duniter sans introduire beaucoup de code. Il fait toujours appel à une preuve de travail uniquement pour assurer un temps constant entre les blocs, mais celle-ci peut être entièrement supprimée si ce temps constant n’est pas voulu ou qu’une autre méthode “d’attente” est trouvée.
- Chaque membre possède une clé publique
P
, et le bloc 0 (ou le premier à passer à cet algo) possède un nonceN
- On calcule pour le nouveau bloc
N = SHA256(previous N)
- Chaque membre peut calculer la “distance”
D = SHA256(P | N)
(où|
est la concaténation, pourrait être remplacée parP xor N
pour travailler avec des variables de taille fixe). Cette étape permet de “mélanger” les membres. (pour limiter de trop grands écarts de distances on pourrait utiliserlog(D)
ou similaire) - Plus
D
est petit, plus le bloc est privilégié. Si un noeud voit arriver plusieurs blocs concurrents, il prendra le bloc avecD
le plus petit. - Pour éviter de pouvoir proposé un
D
plus petit pour des blocs passés, on définit une fonction prenant en compte la distance du bloc courant ainsi que ceux passés, et donnant moins d’importance aux D au fur et à mesure qu’ils sont passés. On pourrait inscrire dans le bloc la “distance cumulée”C
commeC = a * previousC + b * D
,a
etb
étant des réels compris entre 0 et 1;a
controlant “l’atténuation” des distances passées etb
le poids de la derniere distance, et pouvoir déterminer après X blocs quel fork à la plus petite distance cumulée.
Avec un petit programme ou un tableur on pourrait trouver des valeurs de a
et b
pour lesquelles les forks sont résolus en un nombre acceptable de blocs X, nombre de blocs qu’il faut attendre pour être sur que sa transaction est confirmée.
Pour le temps en blocs, soit
- on garde une preuve de travail définissant un interval fixe. En regardant la distance maximum dans une fenetre de bloc, un membre ayant une distance trop grande peut ne pas faire de preuve de travail, sachant qu’il y a très peu de chance qu’elle soit utile
- on garde une petite preuve de travail de quelques secondes pour éviter les spams, on a un temps entre chaque bloc petit et variable, mais en utilisant les dates inscrites dans un “grand” nombre de blocs précédents on peut quand même approximer la date courante. Avoir un temps inter-bloc plus court ne sera pas un problème avec l’utilisation des arbres de Merkle (Duniter 1.7 ?) qui permettra de ne pas stocker l’historique.
- on trouve une autre technique “d’attente”, comme par exemple demander à un certain nombre de membres aléatoires de signer à leur tour le bloc issu s’il est valide, utilisant ainsi la latence réseau pour retarder le bloc (et en ajustant le nombre de membres pour obtenir le temps voulu en moyenne). (augmente la taille des blocs et demande du temps pour vérifier les signatures, mais peut-être que d’autres auront de meilleures idées)
Enfin, il faut inciter les membres à ne pas produire des blocs sur plusieurs forks en même temps. En effet, puisque le nonce ne dépends pas du contenu du bloc, il sera le même sur n’importe quel fork pour un bloc de même id. Si on reçoit 2 blocs différents de même id signés par le même membre (peut importe les forks), on peut inclure ces 2 en têtes dans un bloc suivant et “banir” le membre de l’algorithme pendant un certain nombre de blocs. (vu qu’il n’y a pas de recompense de bloc, je ne vois pas comment inciter autrement un membre à coopérer ) Cette inclusion d’un double bloc pourrait aussi être faite par un autre membre dans un bloc de même id, qui aurait alors un bonus. Ainsi, quelqu’un qui propose 2 blocs concurrents avantagerait avantagerait les autres membres, faisant que ses blocs ont peu de change de faire parti du consensus. (peut-être que ça retirerai le besoin de le banir, mais je ne suis pas sur)
Merci d’avoir lu, et n’hésitez pas à donner votre avis ou des suggestions d’améliorations.