Bug de cesium : Implémentation dépense de sources CSV() et CLTV()

Bonjour,

Je me penche actuellement sur le remplissage automatique des Ğ1Pourboires. Ces pourboires ayant une date de péremption, je me suis dit que ce serait l’occasion parfaite pour implémenter une condition CSV()… Je me base sur du code de Silkaj, dans l’objectif de pouvoir ensuite coder les conditions de dépense directement dans Silkaj.

Les conditions sont :

(SIG({recipient}) || (SIG({sender}) && CSV({delay})))

Soit le récipiendaire utilise sa monnaie avant le délai d’expiration, soit l’émetteur peut la récupérer sans y penser après un délai de péremption, simplement en utilisant son client favori.

J’ai pu émettre des transactions valides (certains essais sont bloqués à tout jamais sur ĞTest :frowning: ) qu’on peut voir par exemple ici : https://ts.gt.librelois.fr/blockchain/block/440714

« 1:2:(SIG(2VgEZnrGQ5hEgwoNrcXZnD9c8o5jL63LPBmJdvMyFhGe) || (SIG(7nge6q7F4k7FQ2q4FRMMPvt2tK7AEx8gNNRLr6LwZN38) && CSV(864))) »

Si je regarde sur Cesium, les conditions de dépense ont l’air bonnes :

Malheureusement, lorsque je veux dépenser la monnaie, elle est bloquée quel que soit le compte que j’utilise (le délai de 14 minutes est largement dépassé). :

silkaj -p ts.gt.librelois.fr tx --output 7nge6q7F4k7FQ2q4FRMMPvt2tK7AEx8gNNRLr6LwZN38 --amount 1 
Please enter your Scrypt Salt (Secret identifier): 
Please enter your Scrypt password (masked): 
2VgEZnrGQ5hEgwoNrcXZnD9c8o5jL63LPBmJdvMyFhGe pubkey doesn’t have enough money for this transaction.

D’où ma question : est-ce une erreur de ma part, ou bien est-ce simplement que Cesium et Silkaj n’ont pas encore implémenté l’utilisation des sources en CSV() et CLTV(), comme je crois le lire ici ?

4 J'aimes

Aucun client (Césium, Silkaj, ni Sakia, ni autre), à ma connaissance, n’a implémenté les autres conditions de déblocage autre que SIG, à savoir CSV, CLTV, et XHX.
Tu es en train d’expérimenter ces nouvelles fonctionnalités du côté client :slight_smile:
Les méthodes pour gérer ces conditions sont implémentées dans DuniterPy. Il reste à en faire bon usage dans les clients Python.

1 J'aime

OK, merci :+1:

Donc je ne vais pas utiliser cette condition pour les Ğ1Pourboires pour le moment, le but étant que ce soit le plus facile pour une personne qui découvre Ğ1.

Mais je vais bosser dessus sur Silkaj, après les MR en cours. Et en commençant par utiliser ces sources.

3 J'aimes

Eh, j’ai deux nouvelles, une bonne et une mauvaise !

Cesium dépense des sources après un délai CSV() passé

La bonne : Si je n’arrivais à rien dépenser, c’est parce que les comptes étaient à 0 : j’avais envoyé moins de 100GT, soit 1GT *10^2 !

Mais depuis j’ai vérifié, avec des envois de 100 GT. La condition d’unlock est :

(SIG({recipient}) || (SIG({sender}) && CSV({delay})))

J’ai envoyé depuis Cesium, une tx avec la SIG(recipient), et une avec la SIG(sender), une fois le délai passé. Les deux ont été validées !

Et lorsque je veux utiliser toute la monnaie du compte (sender) avant le délai, je ne peux pas… Car le délai n’est pas passé, les sources sont bloquées ! J’ai une erreur « wrong unlocker in transaction »

Donc Cesium gère (un peu) la condition CSV(), et les opérandes || et &&. Je suppose que CLTV() fonctionne également. C’est cool !


MAIS Cesium bloque la plupart des tx depuis un compte avant que le délai CSV() soit passé

En revanche, Cesium me refuse certaines transactions depuis le compte « sender », de petits montants, avec la même erreur « Wrong Unlocker ». Donc il ne sait pas trier des sources qui seraient bloquées pour ne pas les utiliser. Autant dire que ce n’est pas encore utilisable pour Ğ1Pourboire.

Par ex. Si un compte a 1000GT dont 100 sont bloquées par CSV(), il ne pourra pas dépenser 500GT car Cesium choisit la mauvaise source, alors même qu’il a 900 GT en sources libres

Conclusion : on peut bloquer TOUTE la monnaie d’un compte sur Cesium en utilisant la condition CSV(), ou en tout cas le rendre quasi inutilisable. C’est un vecteur d’attaque très facile, je peux faire chier qui je veux en lui envoyant une tx avec une condition, Cesium ne saura pas trier le bon grain de l’ivraie. J’ai 10 caractères à modifier dans Silkaj pour faire une telle attaque.

Testé sur Cesium v 1.4.2 et 1.4.6


Et Silkaj ?

Silkaj utilise uniquement les inputs avec SIG(pubkey) comme seule condition. Donc il ne saura pas dépenser les pourboires ou les CSV() passés, mais il ne sera pas non plus bloqué par des tx exotiques : il ne les lit pas.

Vous pouvez regarder les tx émises/reçues par le compte AhRMHUxMPXSeG7qXZrE6qCdjwK9p2bu5Eqei7xAWVEDK sur la GTest.


Solution 1 (court terme): n’utiliser que les conditions de dépenses simples en SIG(pubkey) et rien d’autre, aucune condition composée ni rien d’autre qu’un SIG unique.
Solution 2 (long terme): modifier l’algo de choix des sources pour écarter les sources sous condition de lock.

Et je vais faire un rapport de bug sur Cesium de ce pas. ping @kimamila


Si vous voulez étudier le problème, le compte 6etdjZMRV8p5e5V7AAu4ewChoS3vWrhbh7jn7ZL5g3X6 avec id et mdp : 123456789 a des inputs sous conditions SIG(6etdjZMRV8p5e5V7AAu4ewChoS3vWrhbh7jn7ZL5g3X6) && CSV(5 jours, me demandez pas).

3000 GT en tout, 1200 bloquées.


Si vous appréciez ce rapport de bug, vous pouvez me remercier : CvrMiUhAJpNyX5sdAyZqPE6yEFfSsf6j9EpMmeKvMCWW

3 J'aimes

Rah, tu as été plus rapide que moi à faire joujou avec ces conditions.
Je me disais bien qu’il y aurait de telles choses délectables à découvrir :wink:

Intéressant de savoir que Césium implémente déjà ces conditions.
Mais, vu ce que tu remontes, c’est bugé.

Avec quelques junes (N × 0.01 Ğ1 = 22,40 Ğ1), un Silkaj qui génère des transactions avec ces conditions, un algorithme pour envoyer de telles transactions en masse aux comptes membres récupérés préalablement via BMA, et cette personne a de quoi faire râler la communauté Ğ1/Césium et obliger son développeur à implémenter en urgence l’algorithme de sélection de sources ou faire comme Silkaj et lire que les sources avec condition unique SIG().

3 J'aimes

Vu ce que je rapporte, c’est plutôt que, là où Silkaj gère les outputs avec UNIQUEMENT UN SIG() ; Cesium gère les outputs avec SIG() et ne regarde pas plus loin (si cet output est dépensable ou non). D’où ce bug.

N * 0.01 ?

Je crois qu’il y a des façons plus polies de faire. Mais il est faux d’affirmer que je n’y ai pas pensé tout de suite :smiling_imp:

1 J'aime

Attention a ne pas confondre ce que fait Césium et ce que fait Duniter.
En l’occurrence, Cesium ne sais pas dépenser une source autrement qu’en signant avec SIG.
J’ai juste géré l’affichage des conditions dans l’explorateur de blocs, et commencé a y réfléchir, mais j’en étais resté la, faute d’utilisateur pour tester cela (et surtout de besoin réels).

Si tu as pu dépenser une source qui avait été bloqué, c’est simplement parce-que Duniter l’a renvoyer dans sa liste de sources utilisable, je suppose.

N’est-ce pas plus simple pour de rechercher sa s le code source ? C’est pas si compliqué le JS :slight_smile:

@kimamila Je pense que tu as lu le premier post, et non ce message qui détaille le bug.

Non, je dis que :

Si j’envoie une tx avec condition de lock sur un compte, je peux bloquer toutes les dépenses depuis ce compte faites depuis Cesium, ou en tout cas rendre ce compte inutilisable depuis Cesium.

J’ai également dit que :

Je peux envoyer une tx valide une fois que le délai CSV est passé. Duniter fait donc ce qu’on lui demande.

On est d’accord, par contre il essaie d’utiliser des sources qui ont des conditions de lock supplémentaires. Ceci fait que la tx n’est pas valide… Ce qui bloque la dépense, même s’il y a assez de monnaie sur le compte.

Je peux bloquer le compte portefeuille de ton choix (je n’ai pas essayé les comptes membres) si tu veux un cas à étudier.

Sans doute, mais j’apprends déjà Python.

2 J'aimes

Pour info, j’ai un peu regardé le code, si des devs JS passent par là :

Je ne sais pas coder en JS, cependant je peux vous indiquer les lignes qui me semblent poser souci (v1.4.2) :

5679 :
TX_OUTPUT_SIG: exact(SIG)

7506 :
 var sigMatches =  BMA.regexp.TX_OUTPUT_SIG.exec(outputCondition);

10859 : 
Block.prototype.regexp = {
  TX_OUTPUT_SIG: exact("SIG\\(([0-9a-zA-Z]{43,44})\\)")
};

10881 :
 var matches =  Block.prototype.regexp.TX_OUTPUT_SIG.exec(parts[2]);

En gros, le regexp cherche exactement SIG(pubkey) parmi les outputs reçus, et utilise tout ce qu’il trouve. Dont Cesium va utiliser AUSSI des sources avec conditions de lock non satisfaites, parce qu’il y a effectivement exactement SIG(pubkey) dedans (mais pas que).

J’ai un peu expérimenté, je crois que ceci ne bloque pas les sources D.U., par contre cela bloque les sources recues.

Pour comparaison, la ligne correspondante dans Silkaj est :

    for source in sources["sources"]:
        if source["conditions"] == "SIG(" + pubkey + ")":
2 J'aimes

Ici on a la fonction exact(condition) qui ajoute ^ et $ autour de la condition, donc on est bon :

TX_OUTPUT_SIG: exact(SIG)

Dans https://git.duniter.org/clients/cesium-grp/cesium/blob/master/www/js/services/tx-services.js

On execute TX_OUTPUT_SIG qui est défini comme exact(SIG), donc tout va bien…

 var sigMatches =  BMA.regexp.TX_OUTPUT_SIG.exec(outputCondition);

Le code qui suit me paraît bon, car il fait un match exact avec début et fin de ligne, donc si une autre condition est ajoutée la source ne matche pas.

Dans https://git.duniter.org/clients/cesium-grp/cesium/blob/master/www/js/entities/block.js

   function exact(regexpContent) {
     return new RegExp("^" + regexpContent + "$");
   }

   Block.prototype.regexp = {
     TX_OUTPUT_SIG: exact("SIG\\(([0-9a-zA-Z]{43,44})\\)")
   };

Ici on a une petite boulette sans conséquence, où il faudrait utiliser Block.prototype.regexp.TX_OUTPUT_SIG.exec(unlockCondition);

mais sinon la regexp est la même, donc test strictement un seul SIG()…

      var amount = parts[0];
      var unitbase = parts[1];
      var unlockCondition = parts[2];

      var matches =  Block.prototype.regexp.TX_OUTPUT_SIG.exec(parts[2]);

Etrange, le bug doit être ailleurs. Il faudrait poser des breakpoints…

[edit]
En fait il me semble que ce code refusent les sources ayant des conditions additionnelles. Ce qui a pour effet de les bloquer. Ce qui est normal. En fait je ne voit là rien de grave pour les comptes dans Duniter, juste qu’il n’existe aucun client qui accepte les sources ayant des conditions de dépense multiples.
Mais la solution ne doit pas être d’accepter des sources dont seule une partie est valide. Il faut implémenter la totalité des conditions existantes dans les clients pour débloquer les sources et donc les comptes.
Je ne sais pas si je suis clair ni logique, corrigez moi si je me trompe.

1 J'aime

C’est violent :worried:

2 J'aimes