Paiement simplifié avec GVA: génération du document transaction coté serveur

J’ai ajouté au prototype de GVA une requête permettant de générer un document transaction, je viens de la testée en envoyant @PiNguyen Ğ1 à @vit, et ça a fonctionné :smiley:

  1. indiquez le montant, l’émetteur et le destinataire :

  1. Signez le document fourni

  2. Envoyez le document signé via une mutation :

la procédure est ici simplifiée au maximum, il est impossible de faire plus simple, car la signature du document ne peut pas être faite coté serveur (pour des raisons évidentes de sécurité).

La sélection des sources coté serveur me semble avoir 3 gros avantages :

  1. Les performances : le serveur peut itérer directement sur les sources avec un cursor en base de donnée afin d’arrêter la lecture dès que le montant demandé est atteint. L’envoi d’une transaction sera donc bien plus rapide qu’actuellement car actuellement c’est le client qui télécharge et indexe toutes les sources du compte.

  2. Évite la double dépense en cas d’utilisations de plusieurs clients différents: en effet le serveur peut exclure directement les sources qui se trouvent déjà dans sa mempool. En cas d’utilisation de plusieurs nœuds différents, cet avantage est a modéré en fonction de la synchro des mempool, mais si le même nœud est utilisé entre différents clients (cesium et silkaj par exemple), cela fonctionnera parfaitement.

  3. Simplifie le développement des services tiers ayant besoin de générer des paiements

Notez que le prototype actuel à plusieurs limitations qui seront évidemment résolues à terme :

  • pas encore de vérification des sources déjà en mempool implémenté
  • transactions de changes pas encore gérées
  • Algo naïf, il faut que les 20 premiers DU + 20 premières UTXOs suffissent.

Mais ça marche déjà parfaitement bien pour des petits montant

Le paiement simplifié de GVA fonctionne désormais pour tout montant (sous réserve d’avoir le solde nécessaire bien entendu).

5 J'aimes

Oh oui, continue à faire des tests sur mon compte ! Des bifs ! Des bifs ! :rofl:

1 J'aime

J’essai de générer une transaction en apprenant python: https://git.p2p.legal/poka/py-gva/src/master/pay.py

Lorsque j’envoi un document signé j’obtiens cette erreur:

{'message': 'Mempool full', 'locations': [{'line': 2, 'column': 3}], 'path': ['tx']}

Exemple de document généré et envoyé:

Version: 10
Type: Transaction
Currency: g1
Blockstamp: 373146-00000031C611880A9C2DC0EDD3579A1AD4756F13D74E384E153AAA4127991F87
Locktime: 0
Issuers:
Do99s6wQR2JLfhirPdpAERSjNbmjjECzGxHNJMiNKT3P
Inputs:
1016:0:D:Do99s6wQR2JLfhirPdpAERSjNbmjjECzGxHNJMiNKT3P:331907
Unlocks:
0:SIG(0)
Outputs:
314:0:SIG(Do99s6wQR2JLfhirPdpAERSjNbmjjECzGxHNJMiNKT3P)
702:0:SIG(Do99s6wQR2JLfhirPdpAERSjNbmjjECzGxHNJMiNKT3P)
Comment: Je test un comment
oFeXcvgrkwSNbdIyaU8agVCXouZNbrksBgMJglNdvaGCRaYXpzrxL1lA5kb0za6PllKRb9oE/gOhasoKjKuaCA==

Avec la commande:

./pay.py Do99s6wQR2JLfhirPdpAERSjNbmjjECzGxHNJMiNKT3P 314 "Je test un comment"

Est-ce que la Mempool de ton noeuds est en effet pleine ou est-ce que le soucis peut venir de mon document ?

2 J'aimes

Ni l’un ni l’autre. Je suis en plein développement sur ce prototype de GVA et je maj mon nœud de dev presque tous les jours, il peut donc y avoir régulièrement des régressions.
Ici c’est une régression suite à un refactoring dans la manière de contrôler la gestion de la mempool. Je viens de la corrigée :

Merci pour tes tests, ça m’aide à découvrir les régressions au plus tôt :slight_smile:

Je viens d’envoyer ton document et ça fonctionne, il devrait bientôt s’écrire en blockchain :slight_smile:

4 J'aimes

Ah ok, je suis en train de m’installer un nœud avec GVA sur mon PC, ça sync (sans dbex…) …

Bon bah du coup ça marche, je peux peux effectuer des transactions avec GVA:

./pay.py AhEDcWnSW4SdzidsDYhnDfs75DBpKQKDgHzJzrXdMmB9 213 "VGA: Another wallet"
Version: 10
Type: Transaction
Currency: g1
Blockstamp: 373167-0000000DA0218783A73E0A565DEB98DA070D5C0016EC7F62AE28EEEEC10C2791
Locktime: 0
Issuers:
Do99s6wQR2JLfhirPdpAERSjNbmjjECzGxHNJMiNKT3P
Inputs:
1016:0:D:Do99s6wQR2JLfhirPdpAERSjNbmjjECzGxHNJMiNKT3P:332169
Unlocks:
0:SIG(0)
Outputs:
213:0:SIG(AhEDcWnSW4SdzidsDYhnDfs75DBpKQKDgHzJzrXdMmB9)
803:0:SIG(Do99s6wQR2JLfhirPdpAERSjNbmjjECzGxHNJMiNKT3P)
Comment: VGA: Another wallet
emRtxHSTaqXMpp3R5xibK14Sgiu4onNnqdFqf9jP3STV1au5nO28lSfz++a704afCznitY0+jhOVQi/jcCcuBQ==
{'tx': {'issuers': ['Do99s6wQR2JLfhirPdpAERSjNbmjjECzGxHNJMiNKT3P'], 'outputs': ['213:0:SIG(AhEDcWnSW4SdzidsDYhnDfs75DBpKQKDgHzJzrXdMmB9)', '803:0:SIG(Do99s6wQR2JLfhirPdpAERSjNbmjjECzGxHNJMiNKT3P)'], 'version': 10}}

J’ai bien envoyé cette transaction :slight_smile:

:partying_face:

EDIT: Et non finalement elle a finit en échec.

4 J'aimes

Quand j’essai une transaction via ton noeud de dev, elle reste en attente pendant un moment puis finit en échec.

Quand je test sur mon nœud local ça fonctionne:

(Mais l’écriture en blockchain à bien durée 1h).

Je referais d’autre tests sur ton nœud demain.

1 J'aime

Qu’est ce qui te fait dire qu’elle a fini en échec ? Combien de blocs à tu attendu ? A tu le numéro du bloc d’émission et le numéro du bloc à partir duquel tu a considéré la transaction comme « en échec » ?

Il faut compter en nombre de bloc, pas en temps.
Quand j’avais testé mes premiers paiements GVA la transaction s’écrivait dans les 1 à 3 blocs qui suivaient, ce qui est du même ordre que via BMA.
Or, parfois le temps entre 2 blocs dépasse les 20 min sur la Ğ1. Il m’arrive régulièrement que mes paiements avec Cesium v1 via BMA prenne 1h à s’écrire en blockchain, donc ce n’est pas lié à GVA, pour améliorer ça il faudrait réduire le temps moyen entre 2 blocs.

3 J'aimes

Celle en échec est celle que j’ai mis dans mon poste précédent à 22h29, je n’ai pas pensé à noter le bloc auquel ont était je le ferais désormais.

Elle a commencé à s’afficher en attente sur Cesium, puis à finit par disparaître peut être 1h après.

Elle portait le commentaire VGA: Another wallet vers la clé AhEDcWnSW4SdzidsDYhnDfs75DBpKQKDgHzJzrXdMmB9, elle n’est pas présente dans l’historique des transactions pour cette clé sur Cesium en tout cas.

Mais je viens de refaire un essai sur ton noeud, elle apparaît au bloc 373199 quand je regarde sur le noeud duniter-g1.p2p.legal, mais pas encore validée à l’heure où j’écris.

@poka attention il faut tenir compte des limitations actuelles de l’implémentation, notamment :

Cela signifie que lorsque tu génères un document transaction via GVA, si l’issuer a déjà une transaction en attente alors la transaction générée sera nécessairement invalide car utilisant au moins une même source.
Si tu gardes trace de tout tes documents transaction envoyé je parie que celles en échec ont des inputs déjà pris :wink:

2 J'aimes

Ah oui ça doit être ça, mes essaies suivant on bien fonctionné sur mon noeud local comme sur le tiens.

Le document donc la transaction a finit en échec est celui-ci (le même que plus haut):

Version: 10
Type: Transaction
Currency: g1
Blockstamp: 373167-0000000DA0218783A73E0A565DEB98DA070D5C0016EC7F62AE28EEEEC10C2791
Locktime: 0
Issuers:
Do99s6wQR2JLfhirPdpAERSjNbmjjECzGxHNJMiNKT3P
Inputs:
1016:0:D:Do99s6wQR2JLfhirPdpAERSjNbmjjECzGxHNJMiNKT3P:332169
Unlocks:
0:SIG(0)
Outputs:
213:0:SIG(AhEDcWnSW4SdzidsDYhnDfs75DBpKQKDgHzJzrXdMmB9)
803:0:SIG(Do99s6wQR2JLfhirPdpAERSjNbmjjECzGxHNJMiNKT3P)
Comment: VGA: Another wallet

Donc si je comprends bien la source est mon DU généré au block 332169

Je ne connais pas de moyen simple pour vérifier si cette source a été consommé …

(bon on sort du sujet du coup dsl)

1 J'aime

Il n’y a pas de moyen simple. Il te faut attendre que j’avance sur le développement, probablement dans le WE (où alors générer toi-même le doc tx mais ce ne serait plus du paiement simplifié).

2 J'aimes

@poka je viens de regarder ton script python et il contient une grosse faille de sécurité :

Tu ne vérifies pas le contenu du document transaction avant de le signer, donc le serveur peut en profiter et te fournir un document transaction qui envoie la monnaie sur un autre compte que celui demandé ou/et avec un montant différent. Il te faut à minima vérifier que les outputs et le comment correspondent bien à la demande de l’utilisateur :wink:

2 J'aimes

Ouioui il manque plein de choses c’était juste un test, n’utilisez pas ça en l’état…

J’ai ajouté quelques tests, mais déjà je galère à parser le JSON, la lib gql me sort de simples quotes pour les objets reçus, hors un json valide est composé de doubles quotes il me semble.
Bref j’apprends python ^^

Oui dès que j’arriverai à parser correctement les json je pourrais ajouter des tests pour vérifier que le document est conforme à la demande.

EDIT: J’ai ajouté la vérification de la conformité du document TX :wink:

3 J'aimes

Voila qui est fait : [feat] gva:gen_tx: exclude inputs in mempool on inputs search

Ce fût plus difficile que prévu, notamment car je voulais gérer correctement tous les cas (script quelconque), même si GVA n’expose pas encore cette fonctionnalité.

@poka tu peux tester 2 tx de suite avec le même issuer pour voir si ça fonctionne ? J’ai déjà testé via un TU + sur mon nœud local mais plus il y a de tests mieux c’est.

Pour mettre à jour ton nœud tu peux utiliser la commande suivante :

git fetch && duniter stop && git reset --hard origin/gva-proto-2 && cargo xtask build --production && duniter webstart --gva

EDIT: pas besoin de resync évidemment. Si je ne précise pas c’est qu’il n’y a pas besoin :wink:

1 J'aime

Mon noeud local s’est mis à jour/rebuild sans soucis avec ta commande.
J’ai effectué 3 transactions à la chaine:

Je les vois sur Cesium, j’éditerais quand elles seront validés :slight_smile:

(Inscrites au bloc 373703)

2 J'aimes

Eh ben voila, comme quoi ce n’est pas si compliqué de compiler Duniter :grin:

Génial ça fonctionne nickel :smiley:

3 J'aimes

Alors j’ai travaillé là-dessus hier soir et ce soir, et je me suis rendu compte qu’il est impossible de générer toutes les transactions intermédiaires cotés serveur en l’état actuel du protocole, voici pourquoi :

Les sources de monnaies provenant de transactions antérieures sont identifiées par le hash de la transaction d’origine, or ce hash se calcule à partir du document complet avec signature: il est donc impossible de générer en même temps plusieurs transactions chaînées sans posséder la clé privée de l’émetteur.

On peut évidemment réfléchir à la redéfinition du hash d’une transaction pour une future version du protocole mais ça attendra, car je ne souhaite pas intégrer de nouvelles modifications à DUPBv13 autre que celles prévues afin d’éviter un effet tunnel trop important.

parenthèse effet tunnel

Déjà qu’il n’y a pas eu de nouvelle version de Duniter depuis 5 mois alors que je voulais releaser plus souvent :

Fin septembre j’étais à deux doigts de commencer la campagne de test de duniter 1.9, c’est suite aux demandes de @kimamila que j’ai décidé de retarder la release pour y intégrer un prototype de GVA + réintégrér certains changements du DUBPv13 que j’avais prévu de reporter.


Bref tout ça pour dire que, en attendant, je souhaite tout de même permettre le paiement simplifié de gros montant sans changer le protocole. Voici comment :

Avec deux échanges supplémentaires entre le client et le serveur pour chaque niveau de profondeur.
J’ai conçu un algorithme qui minimise le niveau de profondeur, ce dernier ne sera que de 2 dans la très grande majorité des cas.
Voici un tableau qui résume le nombre d’aller-retour client<->serveur en fonction du nombre de sources de monnaie nécessaire :

Nombre de sources Profondeur AR client-serveur Nombre de tx doc
1-40 1 2 1
41-1600 2 4 2-41
1601-64000 3 6 42-1641
64001-2560000 4 8 1642-65641

On peut continuer le tableau à l’infini, mais dans 99.99% des cas on sera dans la 2ème ligne, même pour des très gros montant, c’est à dire 4 AR client-serveur au lieu de 2 :slight_smile:

L’implémentation est presque terminée, je gère déjà la génération des transactions de change, ce qu’il me manque c’est la prise en compte des sources de monnaie en mempool parmi les sources de monnaies utilisables, détail absolument nécessaire pour que les cas de profondeur 2 ou plus puisse fonctionner sans avoir besoin d’attendre qu’un bloc (voir plusieurs) passe entre chaque étape.

Il est donc théoriquement déjà possible d’envoyer de gros montant via le paiement simplifié de GVA à condition d’avoir beaucoup de temps pour le faire, mais ce n’est pas très pratique, il vaut mieux attendre que j’implémente le «détail» ci-dessus.

2 J'aimes

Si je comprends, cela signifie qu’actuellement les sources exploitables via GVA sont uniquement celles provenant de son propre DU ?
Les sources provenant de d’autres transactions étant inexploitables sans la clé privé de l’émetteur pour retrouvé leur hash ?

Pas sûr d’avoir bien compris mais bon je ne connais pas bien comment Duniter gère ses sources.
En attendant j’ai pas mal amélioré mon micro client GVA pour en faire quelque chose de plus générique.
Il me semble tout à fait exploitable en l’état.

Il ne manquera donc que la gestion des différents aller/retour en fonction du niveau de profondeur à priori.

1 J'aime

Pourquoi 40 ?

pour une tx avec 1 issuer :

  • avec 2 outputs (recipient et backchange) on a au max 46 sources

  • avec 1 output (tx de change) on a au max 47 sources.

edit : @poka j’ai détaillé le calcul ici.

Où vois-tu ça ?
Je ne trouve pas dans la RFC.