Bêta-test Duniter 1.6 WS2P

On ne peut visiblement pas exécuter VirtualBox et QEMU/KVM en même temps (en tout cas pas sans perdre énormément en perf - c’est la partie hyperviseur du CPU/kernel qui ne peut être partagée en deux hyperviseurs distincts), ce qui peut poser problème. Pour ma part, j’ai des machines virtuelles qui tournent sous VirtualBox en permanence, je ne pourrai donc pas faire de build si on se sert de QEMU. Voir par exemple ce thread : https://askubuntu.com/questions/413511/virtualbox-and-kvm-beside-each-other

1 Like

Il n’y avait pas d’erreur de logique à ce niveau, et pas plus ailleurs dans le protocole. Je m’explique.

L’idée générale c’était que pour la Ğ1 l’adhésion expire au bout d’un an (BR_G93), tandis que la révocation implicite se fait au bout de 2 ans (BR_G96). Pour Ğ1-Test c’est plus court, mais on parle en mois tout de même.

Or le temps blockchain n’avance pas de plusieurs mois en 2 blocs. Donc le conflit est impossible avec ces paramétrages :

expires_on = MedianTime + msValidity
revokes_on = MedianTime + msValidity*2

Il n’y a pas besoin de rajouter une condition pour éviter que l’opération se déroule « en même temps », les actions se dérouleront à plusieurs milliers de blocs d’intervalle.

Pourtant, tu me diras, manifestement il y a conflit lors de la synchro. Mais là aussi j’ai bien fait attention à ce que BR_G93 ne se déclenche qu’une fois :

If `MS.expired_on == null OR MS.expired_on == 0` Then

C’est-à-dire que la règle BR_G93 n’agit que si le membre n’a pas déjà son adhésion expirée.

Mais alors pourquoi passe-t-on quand même dans cette condition au même bloc que la révocation implicite (au bloc 79.000+) alors que gerard94 est censé voir son adhésion expirée 40.000 blocs plus tôt ?! Dit autrement, tout se passe comme si l’expiration de l’adhésion de gerard94 au bloc 39312 n’avait pas été enregistrée. Et en effet, c’est bien ça le soucis : la synchro rapide omettait de déclencher cette mise à jour.

D’où le fait que le bug ne se reproduisais pas dans les tests, puisque précisément il n’y avait pas de bug à ce niveau hors « synchro rapide ». Les nœuds ne pouvaient pas planter, il avaient eu 40.000 occasions de bien faire expirer l’adhésion.

Bon et donc quel était le problème ? Dans la synchro rapide, ce code là :

for (const entry of index) {
  if (entry.op === 'CREATE' && (entry.expires_on || entry.revokes_on)) {
    sync_expires.push(entry.expires_on || entry.revokes_on);
  }
}

Aurait plutôt dû être comme ça :

for (const entry of index) {
  if (entry.expires_on) {
    sync_expires.push(entry.expires_on)
  }
  if (entry.revokes_on) {
    sync_expires.push(entry.revokes_on)
  }
}

Traduction :

  • déjà le entry.op === 'CREATE' est complètement hors sujet (@elois l’a bien vu)
  • et aussi on a besoin de refaire les calculs d’expiration à la fois au moment entry.expires_on mais aussi au moment entry.revokes_on, pas juste l’un ou l’autre.

Mais ce n’est pas le cœur du bug. C’est plutôt ce code là qui est censé déclencher le recalcul (en lien avec le code précédant) :

let currentNextExpiring = sync_nextExpiring
sync_nextExpiring = sync_expires.reduce((max, value) => max ? Math.min(max, value) : value, sync_nextExpiring)
const nextExpiringChanged = currentNextExpiring !== sync_nextExpiring

Or ce code de déclenche JAMAIS le recalcul, car nextExpiringChanged vaut toujours false. Correction, en initialisant avec une très grosse date :

let currentNextExpiring = sync_nextExpiring
sync_nextExpiring = sync_expires.reduce((max, value) => max ? Math.min(max, value) : value, 9007199254740991); // Far far away date
const nextExpiringChanged = currentNextExpiring !== sync_nextExpiring

Et du coup là, en effet, on recalcule bien plus souvent.

Bon après, le changement que tu as fait dans le protocole @elois ne fait aucun mal, et même il contourne le bug. Mais c’est plutôt ce code-là qu’il faudrait mettre.

Je vais pousser la modif sur dev.

2 Likes

Qui plus est, il permet d’avoir une monnaie pour laquelle le revocation factor vaudrais 1. En effet on peut très bien décider que dés qu’un compte expire il est immédiatement révoqué, le nouveau protocole permet cela :slight_smile:

1 Like

À noter que dans ce cas, il se produira :

  • bloc#N révocation implicite
  • bloc#N+1 expiration

Ce qui reste totalement compatible avec le protocole. La 2ème étape est “de trop”, mais ne gêne pas.

Mes 2 duniter-ts sont maintenant en 1.6.11 sur g1 et g1-test :slight_smile:

2 Likes

Idem !

2 Likes

Pour faire suite à Nœud Duniter HS, ne pourrait-on pas aussi inscrire dans le message HEAD de WS2P la disponibilité de chaque nœud ? Genre “3/5/10” pour signifier “3 places de prises par des miroirs, 5 par des membres, sur 10 disponibles” et “0/0/0” pour un nœud qui n’aurait pas WS2P public.

Comme c’est un message à faible fréquence (toutes les 5 min environ), ça ne mange pas de pain et aussi cette donnée est disponible via BMA avec l’URL /network/ws2p/heads, donc à la fin de la synchro le nœud pourrait récupérer cette info et saurait où se connecter préférentiellement en dehors des preferedNodes lors de son prochain démarrage.

Si vous avez d’autres idées je suis preneur, car en l’état c’est difficile de livrer la 1.6, on aurait besoin d’une solution pour ce problème de connectivité.

2 Likes

pour réduire le format je propose que le head fournisse plutot le nombre de places dispo pour les INCOMING du noeud correspondant.

Par exemple ajout de deux champs A et B :

A : Nombre de places miroir = nombre réel de places dispo
B: nombre de places membre = A + nombre de miroir non privilégiés actuellement connectés (bah oui ce type de connexion étant moins prioritaire elle laisse sa place en cas de demande de connexion émanent d’un noeud membre)

EDIT : ticket créer : https://github.com/duniter/duniter/issues/1214

1 Like

Hop après 3 soirée et demi mes dev pour la 1.6 sont terminés, tout les test passent et les nouvelles features pour une meilleur connectivité ws2p fonctionnement bien sur mes nœuds membres + 2 nœuds miroirs.

@cgeek @Inso j’attends vos reviews pour merger et builder une nouvelle pré-release : https://git.duniter.org/nodes/typescript/duniter/merge_requests/1208

*J’ai encore un problème avec la web-ui mais ça ne concerne pas cette MR donc je la soumet.

1 Like

Là comme ça je suis incapable de valider cette branche, il y a toutes les features de mélangées dans une seule MR et je n’ai pas bien suivi tout ce que tu as pu faire, notamment au niveau WS2Pv2.

Je crois qu’il y a notre histoire de message HEAD qui ajoute des champs (comme indiqué dans ton message juste au-dessus), mais pour les changements du protocole WS2P lui-même je ne sais pas ce que tu as changé.

As-tu des descriptions quelque part stp ?

Hop voilà le changelog :

En fait je n’ai pas toucher au protocole en lui-même, c’est pour ça que je nomme cette version WS2P 1.1, c’est toujours la version 1 en terme de protocole de communication :slight_smile:

1 Like

Hop un petit aperçu des nouvelles features, voici une capture d’écran des connexions d’un noeud miroir de dev, on voit qu’il a 18 places libres (je venais de le lancer) et on voit en bas qu’il est connecter a l’un de mes 4 nœuds membres, celui pour lequel, step=1. Il reçoit les heads de mes 3 autres nœuds membres par 1 intermédiaire (step=2).
3 ont beaucoup de places car ils ne sont accessibles que par Tor et que très peu de nœuds savent contacter un noeud tor aujourd’hui. Mon seul, noeud accessible en clair est tout le temps plein (0:0).
Lorsque les 2 nombres sont différents, la différences correspond au nombre de connexions miroirs non privilégiés.

j’expliquerai tout ça plus en détail lors de la livraison de la pré-relelase :wink:

Si tu veux bien me laisser un peu de temps, je vais rédiger quelques tests pour m’approprier et vérifier tout cela.

J’ai l’impression que les changements sont assez mineurs, donc ça devrait pas être trop dur. J’en profiterai pour migrer le fameux test WS2P qui échoue aléatoirement.

D’ailleurs je suis en train de voir si l’on ne pourrait pas passer à NodeJS 8 dans le même temps que Duniter 1.6, ça serait vraiment appréciable en termes de performances et de débogage si l’on doit maintenir cette version de Duniter.

Il n’y a pas grand-chose à modifier, juste les scripts de livraison.

4 Likes

Moi ça m’est égal je bénéficie de toute façon toujours des dernières features sans attendre :slight_smile:

C’est aux autres de prendre leur mal en patience !

Oui les changements sont assez mineurs mais il y en a beaucoup, et au final sans change beaucoup de comportements donc ou je te laisse le temps de faire des tests :wink:

Bon, sur un noeud existant que j’ai upgrade à la 1.5.9, reset data et sync sur le noeud du sou, ça fonctionne… presque. :slight_smile:

Mon noeud est isolé :

Il n’est pas joignable de l’extérieur en WS2P mais seulement en BMA. Il devrait quand même pouvoir voir les autres noeuds du réseau non ?

Oui mais que la vue réseau BMA. Donc tu ne verras rien de plus sur cet écran, sauf à ce que WS2P Privé soit activé.

Je ne suis pas sur de comprendre. Ou est-ce que je peux voir les connexions sortantes ?

@Inso tu ne devrait pas avoir cet écran sur la 1.5.9 ou alors tu a upgrader manuellement duniter-ui ?

J’ai upgradé via le duniter-server .deb 1.6.14

Voici ma conf WS2P :

g1@yunohost:/home/admin$ duniter ws2p show-conf
{
 "uuid": "e7177319",
 "privateAccess": true,
 "publicAccess": false,
 "preferedOnly": false,
 "privilegedOnly": false,
 "upnp": true,
 "maxPrivate": 25,
 "maxPublic": 10,
 "remotepath": ""
}

Ca vous parait bon ?

Oui c’est bon, après ça peut venir de yunohost qui des fois désactive l’UPnP c’est un bug que cgeek rencontre régulièrement, vérifie déjà ça.

Ensuite lorsqu’un noeud ws2p, est “nouveau” c’est normal qu’il ne se connecte a personne, il faut un peu de temps, il retente toutes les 10 min donc laisse le tourner au bout de 10, 20 ou 30 min il devrait réussir une 1ère connexion et après se sera plus facile en cas de restart car ils era connu du réseau :wink:

1 Like