RFC GVA > TX compatible avec plusieurs branches

En travaillant sur Cesium 2 et la gestion multi-noeuds, je me demande comment faire pour gérer le cas de fork, afin qu’une transaction émise soit compatible par les branches majoritaires.

Voici un diagramme d’un cas de fork simple (source ici) ou une 1ere transaction génère un fork avec des sources #2 et #2’ différentes (référence de block différente).

La question est :

  • Comment générer les transactions #2 et #2’ qui utiliseraient toutes les sources produites sur chaque branche ?

Evidemment, en théorie, je vois bien comment faire, mais le gros problème, ce sont les performances…

Comment faire, donc, pour :

  • éviter d’interroger à tous les noeuds (pour avoir toutes les sources et leur dernier bloc) ?
  • => on peut sélectionner seulement un noeud par branche, à partir des heads WS2P (à reporter dans GVA, du coup). OK
  • éviter de demander toutes les sources du portefeuille, à chaque noeud de branche interrogé ?
    • Pour éviter cela, il faudrait connaître la liste des sources qui sont spécifique à la branche, et qu’on n’a pas encore en local (dans le client). Je dois donc mettre en place une mini-DB côté client, avec les sources. OK pour ca.
      Mais ensuite, par exemple si on a déjà récupéré les sources #1 #2 et #3 (via un noeud de la branche A)
      comment éviter de redemander la source #1, qui est en commun entre les deux branches ?

Je préssens qu’un arbre de merkle (des sources) pourrait être utile, pour pouvoir synchroniser rapidement les manquantes, mais j’aimerai votre avis. D’autant que les ressources côté client sont limités (espace de stockage et perf de la mini-DB, mémoire vive, etc.). Mais peut-être n’est-ce pas si coûteux ?
De même, côté Noeud GVA, comment faire pour que ne plombe pas les perfs ? A moins de s’appuyer sur autre chose ?

EDIT: j’ai mis à jour le diagramme (en ajoutant les TX #2 qu’on cherche à émettre)

2 J'aimes

Il faudrait surtout appliquer la proposition de @Looarn, a savoir: dans le document transaction remplacer le blockstamp par un blockNumber.

Cela permettais :

  1. Aux clients d’envoyer la transaction sur une seule branche sans se soucier des fork, le document transaction pouvant être le même puisqu’il ne référence aucun hash de block.
  2. Aux nœuds de pouvoir réécrire toutes les transactions d’une branche dans l’autre branche en cas de rollback (aujourd’hui ils sont obligés de détruire les transactions générées après le point de fork).

Mon avis c’est qu’a cause du fait que le document transaction pointe le hash d’un bloc, on est obligés de créer toute une usine a gaz nuisible pour les perf si on veut traiter correctement les transactions comme le montre @kimamila.

Cela fait plus de 6 mois que je réfléchi à la proposition de @Looarn et je n’ai pas trouvé de cas d’attaque possible du fait de ne pointer que le numéro de bloc dans les document transaction.
Certes cela permettra d’émettre des transactions pointant un bloc qui n’existe pas encore, mais les nœuds peuvent très bien rejeter les documents transaction pointant un numéro de bloc supérieur a leur bloc courant.

Comme je vais travailler sur la RFC de DUBP ce Week-End je peut en profiter pour vous faire une proposition de spec :slight_smile:

3 J'aimes

Le souci possible avec le fait de spécifier uniquement le numéro de bloc dans une transaction est que si sur les deux branches les sources du compte émetteur sont consommées différemment, ça peut créer des conflits de consommations de source par la transaction envoyée. Je pense que ça augmente les chances d’avoir des transactions refusées par les nœuds car ayant déjà consommé une source qui serait dans cette nouvelle transaction. En pratique j’ai du mal à imaginer les changements, mais ça me parait cohérent.

Certaine transaction en double spend seront effectivement invalides, c’est le fonctionnement souhaité contre la double dépense.

Le plus ici, c’est que toutes les autres transactions qui elles sont valide (en terme de dépense des UTXO, pourrons passer, et ne seront pas discriminées alors que valide à cause d’un blockstamp qui lui n’héxiste pas.

Non, ça augmente au contraire les chance de voir des transactions légitimes etre validés indépendament du fork. C’est précisément l’inverse. ^^

Effectivement c’est pas un petit dossier, et très structurant, par contre comme le dis @elois on fout à la poubelle une partie de l’usine à gaz, et ça c’est une amélioration.

Double spend : https://en.bitcoin.it/wiki/Irreversible_Transactions

2 J'aimes

Si on enlève le hash, le seul moyen de consommer les sources d’un compte différemment est l’utilisation de plusieurs clients différents en même temps par l’utilisateur final.
Pour un utilisateur n’utilisant qu’un seul client en même temps, ce n’est pas censé arriver, un même client ne vas pas créer plusieurs transactions consommant les mêmes sources, sinon c’est un bug du client.

De plus, le problème que tu décrit ici a lieu que le document transaction pointe le hash ou pas.

Enfin, comme le dit @Looarn, ce n’est pas un problème, c’est une feature :slight_smile:

1 J'aime

Je suis d’accord avec les avantages que vous citez.
J’essaye de décrire le cas que je vois problématique pour que ce soit plus clair pour moi. Si sur une des deux branches la première transaction tx1 n’entre pas la blockchain pour une raison x, alors si la seconde transaction utilise les mêmes sources que tx1, alors tx2 ne passera pas. Au final, une des deux branche vainquera et ça se résoudra en un des deux états. Du coup, c’est pas lié aux branches, ça peut arriver sur une mono-branche ce problème. Donc, c’est bon pour moi.

Est-ce qu’on ferait la même chose pour les autres documents utilisateurs : certification, adhésion, identité et révocation ?

Je ne suis pas sûr de comprendre…
Si les sources #3 et #3’ étaient issues d’un DU, et que la Tx3 en avait besoin pour atteindre le montant escompté, nous sommes d’accord que ces 2 sources porteraient des identifiants différents ? Il faudrait donc bien émettre 2 TX, comme sur le schéma ?

En d’autres termes vous proposer de supprimer le lien fort avec le bloc, mais il y aura toujours un lien fort avec les sources, non ?
En supprimer un ne résoudra pas mon problème.

Ce cas ne peut arriver qu’en cas de mauvaise synchro des piscines. Il faut que le nœud qui forge le 1er block de la branche alternative n’est pas tx1 en mempool. Il suffit qu’un seul des nœuds sur la branche alternative est tx1 dans sa mempool pour que tx1 soit également inscrite sur la branche alternative.

Or, comme tx1 aura le même hash sur les 2 branches, tx2 pourra s’inscrire également sur les 2 branches.

Pour qu’une des 2 branches ne comporte pas du tout tx1 (et donc pas tx2 non plus), il faut que tous les nœud d’une des branches n’est pas tx1 dans leur mempool, cela n’est possible que si les nœuds de cette banche sont très minoritaires.

Dit autrement, en cas de fork, la branche gagnante est forcément majoritaire (sinon elle ne « gagne » pas), et donc il y a forcément au moins 1 nœud sur cette branche majoritaire qui a reçu tx1, sauf bug ou cas de force majeure sur le réseau (coupure de tout un pan d’internet).

la révocation n’est pas concernée car pas blockstampée. Pour les autres documents wot, oui on peut mais c’est moins prioritaire et surtout je ne proposerai que des changements que je suis moi même capable d’implémenter dans Duniter, donc je proposerai le minimum syndical (transactions uniquement).

Pas forcément. l’identifiant d’une source de Type DU c’est PUBKEY:BLOCK_NUMBER. Donc si les 2 branches ont on bloc de création du DU de même numéro c’est bon.
Il faudrait que les 2 branches prennent des rythmes de blocs très différents pour passer l’heure de création du DU a des numéros de bloc différents, 99% des fork étant court (moins de 3 blocs) c’est peu probable en pratique.
De plus, il est rare qu’une transaction consomme le dernier DU tout juste créé, il serait même possible du coté des clients de favoriser la consommation de DU ancien pour rendre ce cas rare encore plus rare.

On passe d’une situation ou il faut 2 tx dans 100% des cas (car les hashs des blocs des 2 branches sont forcément différents ne serait-ce que par variation de l’issuer) à une situation qui ne nécessiterai 2 tx que dans 0,01 % des cas, et encore.

La proposition de @Looarn résout donc ton problème dans au moins 99,99% des cas, ça me semble suffisamment acceptable pour ne pas traiter le cas a la marge de consommation du dernier DU (Quitte a modifier l’algo de sélection des sources coté client pour prioriser le choix des DU les plus anciens).

Pour le problème précis de kimamila, il me semble qu’une solution rapide et simple consiste à se reposer sur de « vieux » blocs, non seulement pour le problème du blockstamp de la transaction mais aussi le n° des sources de DU.

En effet les transactions peuvent se baser sur n’importe quelle autre (chaînage), indépendamment de la branche. Sauf pour le blockstamp, qui ne sert que pour de la mise au rebut de trop vieilles transactions.

3 J'aimes

Exactement, je me souviens avoir proposé cette solution aux rml13 déjà, il suffirait que les clients blockstamp leur transactions à 100 blocs de retard (valeur de rollback maximal). Mais @kimamila ne voulais pas le faire car il se base sur le blockstamp des transactions pour indiquer leurs dates d’émissions sur l’interface utilisateur.

1 J'aime

Proposition de spec réalisée ici : [DUBP V12] Need for a review of the RFC

Ma proposition consiste en le minimum syndical pour éviter les régressions : le format des transaction reste identique et il n’y a rien a changer coté client. Simplement, lors de la validation globale, les noeuds duniter ne vérifieront plus le hash pointé par la tx, c’est tout :slight_smile:

Dans la pratique, modifier le code de la validation globale ne suffira pas, il faudra aussi supprimer le contrôle dans le code de génération du prochain block (et peut-être aussi dans le code qui réinjecte en mempool les transactions lors d’un rollback), mais ces portions de code ne sont pas régies par la RFC du protocole.

EDIT : Après analyse du code de Duniter, il semble que lors d’un rollback toutes les transactions sont remises en mempool sans contrôle : https://git.duniter.org/nodes/typescript/duniter/blob/dev/app/lib/blockchain/DuniterBlockchain.ts#L406

Si possible, j’aimerai garder une référence au temps.
Par ailleurs, j’ai plus souvent qu’on le croit le problème d’usage des toutes dernières sources (même <100 blocs). Et j’aurais aimé trouver une solution globale…

Avec juste le blockNumber sans le hash, dans la TX, ne me plaît gère. Ça permettra d’emettre des TX dans le futur, ce qui n’a aucun sens a mon avis.
Enlever le hash me paraît une perte de fonctionnalité.

Une solution que je propose est de pouvoir indiquer plusieurs blockstamp, dans la TX.
Si au moins un blockstamp est valide, alors le noeud l’accepte.
Ainsi, les TX dans le futur sont impossible, et une TX peut être émises et acceptées par plusieurs blocs.

Le numéro de bloc suffit a donner une référence au temps. On peut faire en sorte que GVA donne automatiquement le blockchainTime du numéro de block correspondant.

La solution de @Looarn est déjà globale pour les UTXOS, quand aux sources de type DU comme il n’en est créée qu’une tout les 288 blocs tu en aura au plus une seule dans les forkWindowSize derniers blocs.

Aujourd’hui tu a souvent les dernières sources car l’algo de selection des sources prend les 1ères qu’il trouve, il suffit de modifier l’algo de sélection des sources.

Non comme je l’ai indiqué plus haut il ne sera pas possible d’émettre des TX dans le futur. Si un noeud à pour bloc courant le 512 et qu’il reçoit une transaction indiquant pour bloc courant 514 celle ci sera refusée comme actuelle. La présence ou non de la contrainte sur le hash n’y change rien.

En quoi est ce une perte de fonctionnalité ? J’ai l’impression en vue de ton dernier message que tu n’a pas tout lu car tu fait des remarques qui déjà été démenties.

Trop lourd, ça ne respecte pas le principe KISS, je suis vraiment opposé a une telle idée surtout que je n’ai toujours pas entendu d’objection pertinente au retrait de la contrainte sur le hash.

Pour la référence au temps, il faut voir à quoi elle te sert. Selon le cas le temps blockchain peut être intéressant ou pas, faut voir.

Concernant le problème d’usage des toutes dernières sources j’ai déjà réfléchi au problème et je pense avoir une solution telle que les clients n’auraient même plus à se soucier de cela.

Enfin pour la TX dans le futur, tu as bien évidemment raison : il est impossible de forger une telle transaction si le hash est requis, tandis que c’est possible sans. Là-dessus c’est bel et bien une perte de fonctionnalité (mais aussi la création d’une ou plusieurs autres).

Mais à la limite, ça regarde chaque nœud de gérer ces transactions comme ils l’entend. Certains les refuseront (position que défend Eloïs), d’autres les accepteront (position qui me paraît aussi défendable car elle peut avoir son intérêt). Toutefois le protocole garantira qu’une TX dans le futur est forcément en attente de parution du n° de bloc visé.

2 J'aimes

Il me semble que pour @kimamila la référence au temps sert a indiquer la date et l’heure d’émission des transactions dans l’historique des transactions d’un compte. Cette date et heure ne peuvent pas être positionnées dans le futur pour les transactions en blockchain.

Concernant les transactions en mempool, je considère qu’il n’y a pas lieu qu’il y en ai non plus, en tout les cas Dunitrust ne le permettra pas, et Duniter ne le permet pas aujourd’hui, si j’implémente ma proposition dans Duniter, je ferai en sorte qu’il ne le permette pas. Libre a cgeek ou d’autres dev de Duniter d’autoriser un tel cas, mais je pense que la pratique restera marginale et ne faussera donc que très rarement la date et heure affichée dans l’historique des transactions et uniquement pour les transactions en attente de toute façon.
De plus, rien ne t’empêche @kimamila de borner l’affichage au temps ajusté du bloc courant, de sorte que l’utilisateur final ne verra jamais une date dans le futur.

Il conviens de peser le pour et le contre de chaque proposition pour l’utilisateur.

  1. Conserver l’état actuel
  • Transactions perdue en cas de fork (ce qui arrive très fréquemment)
  • Impossibilité de générer un document transaction qui pointe un bloc futur (ce qui n’apporte rien a l’utilisateur final)
  1. Remplacer le check du blockstamp par le check du blockNumber
  • Transactions correctement traités en cas de fork (acceptées sur toutes les branches, sauf dans le cas très marginal de consommation du dernier DU, qui viens d’être créé dans le fork en cours et avec un bloc du dividende à numéro différent dans les 2 branches).
  • Possibilité de générer un document transaction qui pointe un bloc futur (ce qui n’impacte en rien l’utilisateur final comme montré plus haut).

La vrai question @kimamila c’est : existe t’il au moins un besoin des utilisateurs de Cesium qu’apporte le contrôle du blockstamp des transactions et qui ne peut pas être apporté autrement ?
Si un tel besoin n’existe pas (ce que je pense), alors il me semble irrationnel de vouloir conserver le contrôle du blockstamp des transactions :wink:

Cher @elois, j’ai le sentiment qu’il ne faut pas se précipiter a retirer le hash.

C’est actuellement la seule référence au temps vérifiable. Si on garde juste le blockNumber, alors autant tout retirer car cela ne veut plus rien dire du tout.
Or, qu’essayons de bâtir ? Une économie réelle, basée sur un temps humains. Les vrais gens ne font pas de transaction dans le futur.

Certes, cela peut arriver qu’on demande a encaissé seulement a la fin du mois, mais justement de le fait de déposer directement le paiement avec une condition (output) de déblocage me paraît mieux que le système actuel, vis a vis du vendeur. Car la monnaie est comme « mise en gage ».

Tu dis que tu ne garderas pas les TX dans le futur, mais tu seras bien obligé, ne serait-ce que sur les dernier blocs N+100, on est d’accord ?

Bon, après je vois bien aussi tous les avantages de la solution de @Looarn. Notamment, on pourra faire des paiements chainés, même hors connexion, et ça s’est plutôt cool.

C’est pas tellement plus vrai qu’avec le hash, car il faut quand même connaître le numéro « a peu près courant » de la blockchain pour que la transaction soit acceptée.

Et puis je crois qu’il exite toujours la péremption au bout de 7 jours d’une transaction. Donc le n° de bloc ne peut pas être pris totalement au hasard.

Enfin concernant la référence en tant que date, pourquoi ne pas plutôt prendre la date du bloc qui inclut la transaction ? Si l’on considère que les transactions sont en moyenne intégrées quelques minutes après leur émission, alors cette date est suffisante. Non ?

2 J'aimes

Cher @kimamila, on ne se précipite pas, ça fait plus de 6 mois que l’idée a été émise. J’ai le sentiment que tu t’accroche irrationnellement a la vérification d’un hash qui apporte plus d 'inconvénients que d’avantages. :wink:

En quoi est ce plus vérifiable ? Mais surtout, qu’apporterais cette vérifiabilité supplémentaire supposée ? Dans le sens, a quel besoin répond elle ?

Je n’ai jamais dit le contraire, et ça me semble hors-sujet, en quoi cela défend t’il un besoin de garder le hash ?

Non on n’est pas d’accord, les conditions d’acceptation d’un document en mempool n’ont pas de rapport avec le rollback maximum, il me semble que tu mélange ici des aspects indépendants.


Oui cette péremption au bout de 7 jours (txWindow) sera conservée.

Oui c’est en effet ce qui peut être fait pour les transactions inscrites en blockchain.

1 J'aime

C’est pas vraiment ce que je constate, kimamila t’as déjà répondu que le hash est une perte de fonctionnalité selon lui notamment car il s’agit du seul temps vérifiable.

Le hash permet de dire « cette transaction a été émise avant telle date » de façon certaine, qui par ailleurs combiné à la règle de 7 jours de validité donne un intervalle certain d’émission. Ce qui n’est plus possible sans celui-ci, on perd une de ces deux bornes.

Côté utilité, on peut regarder du côté des documents de WoT là où cette donnée a été explicitement voulue, par exemple les certifications : ce bornage par le hash empêche formellement la constitution d’un stock. Cela protège l’utilisateur de lui-même en limitant sa capacité de certification dans un intervalle de temps donné car une fois émise une certification est incontrôlable.

A priori je ne vois pas de cas similaire pour les transactions. Mais ça ne veut pas dire qu’il ne faut pas continuer à chercher, car une fois cette fonction perdue il existera un précédent.

Le bébé, l’eau du bain, tout ça. Et restons bienveillants.

1 J'aime

Le contrôle du hash assure seulement de l’impossibilité de générer un document qui pointe un bloc qui n’existe pas encore, c’est bien ce que j’avais répondu a @Looarn il y a 6 mois, et après avoir tourner la question en long en large et en travers, je ne vois aucune raison d’assurer cette impossibilité.
D’ailleurs, il est déjà possible de générer un document dans le passé, et ça ne semble gêner personne :wink:

Le sujet ici se sont les transactions,restons dans le sujet svp afin de ne pas s’égarer. Concernant les documents de la wot, vous pouvez ouvrir un autre fils :slight_smile:

J’estime justement qu’on a suffisamment cherché, surtout que cela est pratiqué dans les autres crypto rependues tel que bitcoin et que ça n’a jamais posé de problèmes connus.