Vu certains posts sur le fil Options pour gérer les commentaires de transaction côté serveur, il me semble utile de faire un rappel sur l’élagage de l’état ou des blocs, et les différentes configurations possibles pour un nœud Duniter.
Options disponibles
Il y a deux types d’élagages possibles : le state pruning et le block pruning.
> duniter --help
--state-pruning <PRUNING_MODE>
Specify the state pruning mode.
This mode specifies when the block's state (ie, storage) should be pruned (ie, removed) from the
database. This setting can only be set on the first creation of the database. Every subsequent run
will load the pruning mode from the database and will error if the stored mode doesn't match this
CLI value. It is fine to drop this CLI flag for subsequent runs. Possible values: - archive: Keep
the state of all blocks. - 'archive-canonical' Keep only the state of finalized blocks. - number
Keep the state of the last number of finalized blocks. [default: 256]
--blocks-pruning <PRUNING_MODE>
Specify the blocks pruning mode.
This mode specifies when the block's body (including justifications) should be pruned (ie, removed)
from the database. Possible values: - 'archive' Keep all blocks. - 'archive-canonical' Keep only
finalized blocks. - number Keep the last `number` of finalized blocks.
[default: archive-canonical]
L’élagage des états permet de ne conserver que les états récents, mais les états anciens peuvent toujours être reconstruits à partir de l’historique des blocs.
L’élagage des blocs permet de ne conserver que la tête utile pour ajouter de nouveaux blocs, mais ne permet plus la reconstruction de l’historique.
Noms simplifiés
Pour simplifier l’utilisation, nous avons introduit la variable d’environnement DUNITER_PRUNING_PROFILE
pour la configuration via docker, cf docker entrypoint (L67-L80). Pour un nœud validateur, on recommande d’utiliser le profile “light” : Duniter | Run a smith node car le reste serait superflu. Bien entendu, cela implique de conserver par ailleurs des nœuds miroir a minima pour éviter de perdre l’historique. Pour faire tourner duniter-squid, il faut lui fournir un endpoint d’un nœud archive, de préférence local parce qu’il y aura beaucoup de requêtes.
Pour simplifier la compréhension, je propose de nommer les nœuds en sous-entendant le profile associé :
- forgeron → light (élagage d’état et des blocs)
- miroir → default (uniquement élagage d’état)
- archive → archive (pas d’élagage)
Remarques
Un nœud “miroir” n’élague que les états, donc il stocke quand même les blocs, ce qui est nécessaire pour pouvoir reconstruire l’historique des états.
Un nœud “archive” conserve en plus un historique de la Patricia Merkle Tree des états, donc dans le cas des commentaires de transaction, un simple pointeur vers les événements contenus dans les blocs.
Pour moi les évènements sont stockés sur tous les noeuds, car ce n’est pas un état du storage et donc le droit à l’oubli est impossible.
Je m’etait posé la question car je trouvais dangereux pour la blockchain de potentiellement perdre des informations à jamais si plus personne ne faisait tourner de noeud archive.
Quand j’ai compris que la seule difference entre un noeud archive et un noeud simple est l’historique des états du storage à chaque bloc, et que l’on peut donc reconstruire un noeud archive à partir d’un noeud simple, j’etais rassuré.
Mais je vais chercher la preuve de cela dans la doc Substrate parce que c’est important.
Les événements font partie des blocs (de leur merkle tree), donc sont stockés sur les nœuds qui ne les élaguent pas.
On peut reconstruire un nœud archive à partir d’un nœud miroir, mais pas à partir d’un nœud light.
les évènements n’étant pas nécessaires à la State Transition Function (STF), je ne vois aucune raison de les conserver lors de l’élagage d’un bloc
Effectivement. Les événements sont dans le storage uniquement parce que les blocs sont dans le storage (via leur state root). Donc quand on élague un bloc (nœud light), l’événement disparaît. Par contre, il est conservé sur les nœuds miroir.
Je pense qu’une mauvaise compréhension du comportement du Storage rôde dans l’air (je m’inclus dedans) et cause ces incompréhensions.
d’où ce sujet
les événements sont purgés au delà du nombre de bloc configuré par l’option purge (256 par défaut je crois)
On ne “prune” les blocs (pas “purge”) que pour le profile “light”.
Je trouve la doc Substrate très pauvre sur ces sujets, j’ai beaucoup de mal à trouver des informations détaillés sur ces sujets.
Cgeek avait partagé une présentation vidéo que je ne retrouve plus, mais les slides sont ici :
https://polkadot-blockchain-academy.github.io/pba-book/substrate/storage/slides.html#/
Reformulations
Vous trouverez tout ça formulé autrement dans le post Options pour gérer les commentaires de transaction côté serveur - #21 by cgeek
citation
C’est à peu près ce que j’essaye d’exprimer oui, je vais le reformuler :
Je pars du principe (possiblement erroné, ça reste à confirmer) que, bien que toute écriture de donnée impacte le Storage (la BDD, en gros) et notamment le Merkle Root du bloc courant, toute écriture ne va pas forcément impacter le Merkle Root des blocs suivants.
Autrement dit : que quand un bloc est traité et accepté, il va construire son propre arbre de Merkle dont certaines branches vont “reprendre” tout ou partie des données de l’état au bloc précédent, mais que certaines autres branches seront purement et simplement écrasées.
Je prétends que les évènements font partie de ces données systématiquement écrasées en intégralité par chaque bloc, et que donc par définition ce type de donnée n’impacte pas les blocs suivants et que forcément, à l’élagage du bloc, la donnée disparaît et ne vient jamais “gonfler” la BDD contrairement à des données “métier” (les comptes, les transactions, etc.).
Voilà pourquoi les évènements me semblent une très bonne façon d’indexer les hash de commentaires.
Et c’est également pour cela que je dis que stocker ces hash comme une donnée “métier” viendrait au contraire créer une donnée stockée par tout nœud (archive ou pas) et créerait même une donnée à stocker de façon historisée pour un nœud archive (en gros = stocker tous les évènements de tous les blocs).
edit : tiens bah je suis allé vérifier sur la documentation Substrate, c’est bien comme ça que ça se passe :
This function places the event in the System pallet’s runtime storage for that block. At the beginning of a new block, the System pallet automatically removes all events that were stored from the previous block.
Et au sujet de la reconstruction de l’état.
citation
Oui, je suppose que le nœud full conserve les blocs avec body (donc avec les extrinsics dedans) tandis qu’un light node par exemple ne synchronise que le header de chaque bloc. Ce qui fait que ce dernier type de nœud est le seul à ne pas pouvoir reconstruire l’intégralité des données de la blockchain, tous les autres le peuvent.
Autre reformulation par tuxmain.
citation
Je ne comprends pas quel est le débat. Pour récapituler :
- La blockchain est une suite de blocs.
- Les blocs contiennent des extrinsics.
- Les nœuds d’archive ont tous les blocs.
- Les nœuds normaux ont seulement les derniers blocs.
- Le runtime exécute du code pour chaque extrinsic, qui peut générer des événements et modifier l’état, de manière déterministe (fonction du bloc et de l’état).
- Les événements ne sont pas stockés.
Donc :
- Les extrinsics sont publics.
- Les événements peuvent être retrouvés facilement à partir d’une archive (on prend un ancien état soit à partir d’une archive des états, soit en enchaînant les anciens blocs, et on exécute le bloc suivant).
Les événements ne sont là que pour aider les indexeurs et clients.
Voilà, j’espère que ça permettra de reprendre la discussion sur : veut-on que les hash des commentaires de tx fassent partie du consensus “dur” en blockchain, ou préfère-t-on que cela fasse partie d’un consensus “mou” hors blockchain.