# Ancien membre de retour avec seulement 4 certifications

**URL:** https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712
**Category:** Duniter-v1
**Tags:** duniter, bug, exclusion
**Created:** [30 December 2019 20:51 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712 "2019-12-30T20:51:08Z")
**Posts on this page:** 20
**Page:** 2

<div class="post-metadata">

### Author: ![cgeek](https://forum.duniter.org/user_avatar/forum.duniter.org/cgeek/32/279_2.png) [@cgeek](https://forum.duniter.org/u/cgeek)
#### Post date: [7 January 2020 12:08 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/21 "2020-01-07T12:08:11Z")

</div>

C’est tout à fait à cette solution que je pensais. 🙂

---

<div class="post-metadata">

### Author: ![SimonLefort](https://forum.duniter.org/user_avatar/forum.duniter.org/simonlefort/32/3875_2.png) [@SimonLefort](https://forum.duniter.org/u/SimonLefort)
#### Post date: [7 January 2020 12:10 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/22 "2020-01-07T12:10:56Z")

</div>

C’est pas du tout compliqué… 😃

---

<div class="post-metadata">

### Author: ![gerard94](https://forum.duniter.org/user_avatar/forum.duniter.org/gerard94/32/58_2.png) [@gerard94](https://forum.duniter.org/u/gerard94)
#### Post date: [7 January 2020 13:06 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/23 "2020-01-07T13:06:28Z")

</div>

Petit détail :

> [@elois](#):
>
> REDUCE\_BY(CONCAT(GLOBAL\_CINDEX[receiver=ENTRY.pub,expired\_on=null], LOCAL\_CINDEX[receiver=ENTRY.pub,expired\_on=null]), ‘issuer’, ‘receiver’)

Dans la mesure où on a déjà sélectionné un seul receiver, est-il utile de réduire par receiver ?

---

<div class="post-metadata">

### Author: ![elois](https://forum.duniter.org/user_avatar/forum.duniter.org/elois/32/1541_2.png) [@elois](https://forum.duniter.org/u/elois)
#### Post date: [7 January 2020 13:45 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/24 "2020-01-07T13:45:41Z")

</div>

En effet on peut simplifier 🙂

Voici la version simplifiée :

`ENTRY.enoughCerts = COUNT(REDUCE_BY(CONCAT(GLOBAL_CINDEX[receiver=ENTRY.pub,expired_on=null], LOCAL_CINDEX[receiver=ENTRY.pub,expired_on=null]), 'issuer')) >= sigQty `

---

<div class="post-metadata">

### Author: ![elois](https://forum.duniter.org/user_avatar/forum.duniter.org/elois/32/1541_2.png) [@elois](https://forum.duniter.org/u/elois)
#### Post date: [7 January 2020 13:50 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/25 "2020-01-07T13:50:33Z")

</div>

> [@cgeek](#):
>
> C’est tout à fait à cette solution que je pensais.

Ok, souhaite tu que je l’ajoute au draft de la RFC v12 ? (la version simplifiée après remarque de gerard94)

---

<div class="post-metadata">

### Author: ![Moul](https://forum.duniter.org/user_avatar/forum.duniter.org/moul/32/9145_2.png) [@Moul](https://forum.duniter.org/u/Moul)
#### Post date: [7 January 2020 14:04 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/26 "2020-01-07T14:04:14Z")

</div>

Oui, c’est bien d’ajouter ce correctif du protocole dans la v12.  
Ça ne nécessitera pas de déclenchement par changement de version de bloc.  
Juste un correctif du code qui peu être délivré à un moment différent afin de respecter cette version du protocole.

---

<div class="post-metadata">

### Author: ![elois](https://forum.duniter.org/user_avatar/forum.duniter.org/elois/32/1541_2.png) [@elois](https://forum.duniter.org/u/elois)
#### Post date: [7 January 2020 16:27 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/27 "2020-01-07T16:27:15Z")

</div>

Une variante plus optimisée (sans REDUCE\_BY) :

`ENTRY.enoughCerts = COUNT(UNIQ(CONCAT(PICK(GLOBAL_CINDEX[receiver=ENTRY.pub,expired_on=null], 'issuer'), PICK(LOCAL_CINDEX[receiver=ENTRY.pub,expired_on=null]], 'issuer')))) >= sigQty`

1. On extrait le set des issuers des certifications inscrites
2. On extrait le set des issuers des certifications pending
3. On concatène les deux set d’issuers
4. On supprime les doublons
5. On compte

---

<div class="post-metadata">

### Author: ![cgeek](https://forum.duniter.org/user_avatar/forum.duniter.org/cgeek/32/279_2.png) [@cgeek](https://forum.duniter.org/u/cgeek)
#### Post date: [8 January 2020 11:19 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/28 "2020-01-08T11:19:26Z")

</div>

> [@elois](#):
>
> Ok, souhaite tu que je l’ajoute au draft de la RFC v12 ?

Oui ce serait bien. Avec la version que tu souhaites, les deux solutions proposées étant correctes a priori.

---

<div class="post-metadata">

### Author: ![cgeek](https://forum.duniter.org/user_avatar/forum.duniter.org/cgeek/32/279_2.png) [@cgeek](https://forum.duniter.org/u/cgeek)
#### Post date: [9 January 2020 18:59 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/29 "2020-01-09T18:59:43Z")

</div>

Pour info : je n’ai pas encore fini l’investigation, ce n’est pas si long mais j’ai peu de temps. En tout cas je développe de nouveaux outils de débogage qui seront bien utiles, je vous les partagerai bien entendu.

edit : bug identifié (en plus de celui du protocole, c’est le bug qui empêche la résolution de fork) dans la méthode [findByReceiverAndExpiredOn()](http://git.duniter.org/nodes/typescript/duniter/blob/master/app/lib/dal/indexDAL/leveldb/LevelDBCindex.ts#L215-215). Saurez-vous le trouver ?

---

<div class="post-metadata">

### Author: ![Moul](https://forum.duniter.org/user_avatar/forum.duniter.org/moul/32/9145_2.png) [@Moul](https://forum.duniter.org/u/Moul)
#### Post date: [9 January 2020 19:46 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/30 "2020-01-09T19:46:06Z")

</div>

```diff
-- return (await this.get(issuer)).issued.filter(e => e.receiver === pub && e.expired_on === 0)
++ return (await this.get(issuer)).issued.filter(e => e.receiver === pub && e.expired_on === expired_on)

```

?

---

<div class="post-metadata">

### Author: ![elois](https://forum.duniter.org/user_avatar/forum.duniter.org/elois/32/1541_2.png) [@elois](https://forum.duniter.org/u/elois)
#### Post date: [9 January 2020 20:27 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/31 "2020-01-09T20:27:10Z")

</div>

> [@cgeek](#):
>
> dans la méthode [findByReceiverAndExpiredOn()](http://git.duniter.org/nodes/typescript/duniter/blob/master/app/lib/dal/indexDAL/leveldb/LevelDBCindex.ts#L215-215). Saurez-vous le trouver ?

> **Ma réponse :**
>
> La méthode `findByReceiverAndExpiredOn` retourne toutes les lignes de l’index  
> CINDEX qui concernent une certification reçue par l’intéressé. Il manque un reduceBy([‘issuer’, ‘receiver’]).  
> D’ailleurs perso je supprimerai cette méthode et je remplacerai le seul appel par `getValidLinksTo` qui ferait parfaitement bien le job pour la BR\_G27 🙂

@Moul non ce n’est pas ça car le seul appel a cette fonction ce fait avec la valeur zéro pour expired\_on 😛

---

<div class="post-metadata">

### Author: ![elois](https://forum.duniter.org/user_avatar/forum.duniter.org/elois/32/1541_2.png) [@elois](https://forum.duniter.org/u/elois)
#### Post date: [9 January 2020 20:52 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/32 "2020-01-09T20:52:39Z")

</div>

> [@elois](#):
>
> Ok, souhaite tu que je l’ajoute au draft de la RFC v12 ?

> [@cgeek](#):
>
> Oui ce serait bien.

It’s done 🙂

J’ai créé un ticket lié sur le dépôt des RFC, je pense que c’est l’endroit idéal pour tracer les défauts de spec : [BR\_G27: do not count certifications being replayed twice (#11) · Issues · nodes / common / doc · GitLab](https://git.duniter.org/nodes/common/doc/issues/11)

Et j’ai ajouté le correctif à la RFC v12 :

> [@\[DUBP V12\] RFC approved](https://forum.duniter.org/t/dubp-v12-need-for-a-review-of-the-rfc/6656/4):
>
> A commit h…

---

<div class="post-metadata">

### Author: ![cgeek](https://forum.duniter.org/user_avatar/forum.duniter.org/cgeek/32/279_2.png) [@cgeek](https://forum.duniter.org/u/cgeek)
#### Post date: [10 January 2020 11:42 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/33 "2020-01-10T11:42:10Z")

</div>

Alors oui, Moul, il y a ce bug mais voir la réponse d’Eloïs sur ce point. Mais je vais effectivement changer pour ta version.

> [@elois](#):
>
> La méthode `findByReceiverAndExpiredOn` retourne toutes les lignes de l’index  
> CINDEX qui concernent une certification reçue par l’intéressé. Il manque un reduceBy([‹ issuer ›, ‹ receiver ›]).

Alors il manque effectivement la réduction, et oui c’est bien le cœur du problème mais pas exactement comme tu l’exprimes. En fait c’est l’élagage qui fait que cette méthode renvoie deux résultats différents selon l’état du CINDEX “élagué” ou “non élagué”.

Le protocole s’exprime dans un référentiel (index) non élagué, mais pour des raisons de performances Duniter élague ses index. Or dans le cas présent, la méthode `findByReceiverAndExpiredOn` buguée est sensible à l’élagage. Si le protocole avait été correct toutefois (s’il avait requis une réduction via la fonction `REDUCE`), elle ne l’aurait pas été et nous n’aurions pas eu de problème de résolution ce début d’année 2020.

---

<div class="post-metadata">

### Author: ![cgeek](https://forum.duniter.org/user_avatar/forum.duniter.org/cgeek/32/279_2.png) [@cgeek](https://forum.duniter.org/u/cgeek)
#### Post date: [10 January 2020 20:53 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/34 "2020-01-10T20:53:27Z")

</div>

> [@elois](#):
>
> Une variante plus optimisée (sans REDUCE\_BY)

Non là c’est faux (en fait, les 3 propositions le sont), il faut le REDUCE\_BY **et il faut fermer la fonction avant de filtrer** sur `expired_on=0`, sinon ça ne sert à rien car cette condition est toujours vraie sans réduction : quand une certification est créée (op=CREATE), alors expired\_on vaut 0 (et pas `null` d’ailleurs, c’est une erreur qui traîne dans le protocole) donc on retrouve systématiquement les certifications initiales du membres lors de son entrée dans la monnaie.

Du coup je propose :

```auto
BLOCKCHAIN = REDUCE_BY(GLOBAL_CINDEX[receiver=ENTRY.pub], 'issuer')[expired_on=0]
INCOMING = LOCAL_CINDEX[receiver=ENTRY.pub]
UNIQUE_ISSUERS = UNIQ(CONCAT(
    PICK(BLOCKCHAIN, 'issuer'),
    PICK(INCOMING, 'issuer')))
ENTRY.enoughCerts = COUNT(UNIQUE_ISSUERS) >= sigQty

```

À noter qu’il n’y a pas besoin de filtrer sur l’expiration pour les certifications entrantes, juste sur celles en blockchain.

---

<div class="post-metadata">

### Author: ![elois](https://forum.duniter.org/user_avatar/forum.duniter.org/elois/32/1541_2.png) [@elois](https://forum.duniter.org/u/elois)
#### Post date: [10 January 2020 22:05 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/35 "2020-01-10T22:05:01Z")

</div>

Je reformule pour voir si j’ai bien compris (et pour aider les lecteurs aussi) :

L’index `GLOBAL_CINDEX` comprend toutes les certifications passées et présentes, y compris celles qui ont déjà expirées. Or on ne veut que celles qui n’ont pas encore expirées.

Chaque ligne d’index correspond a un “évenement”, pour les certifications, il y a 3 evenements possibles :

- création
- renouvellement
- expiration

Le champ `expired_on` indique le timestamp auquel la certification a expirée, la valeur 0 indique que la certification n’a pas expirée.  
Lors de la création, `expired_on` vaut 0.  
Lors de l’expiration, `expired_on` vaut la date d’expiration.  
Lors du renouvellement, je suposse que `expired_on` vaut zéro (mais ce n’est pas spécifié explicitement et je n’ai pas vérifié dans le code).

Si on ne fait pas de REDUCE\_BY, on vas compter toutes les lignes d’index pour lesquelles `expired_on == 0`, or certaines lignes d’index concernent le passé, donc sans REDUCE\_BY on compte les certifications expirées.

Donc en effet, il faut un `REDUCE_BY('issuer')` dans tout les cas.

* * *

> [@cgeek](#):
>
> alors expired\_on vaut 0 (et pas `null` d’ailleurs, c’est une erreur qui traîne dans le protocole)

Erreur corrigée dans la RFC v12 🙂

---

<div class="post-metadata">

### Author: ![cgeek](https://forum.duniter.org/user_avatar/forum.duniter.org/cgeek/32/279_2.png) [@cgeek](https://forum.duniter.org/u/cgeek)
#### Post date: [11 January 2020 08:55 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/36 "2020-01-11T08:55:38Z")

</div>

Oui c’est bien cela. Je vais re-détailler le cas de GerardSiegle plus précisément plus tard, tout paraîtra évident.

> [@elois](#):
>
> Lors du renouvellement, je suposse que `expired_on` vaut zéro (mais ce n’est pas spécifié explicitement et je n’ai pas vérifié dans le code).

Oui il vaut zéro, à cet endroit du protocole :

##### Certifications

Each certification produces 1 new entry:

```auto
CINDEX (
    op = 'CREATE'
    issuer = PUBKEY_FROM
    receiver = PUBKEY_TO
    created_on = BLOCK_ID
    written_on = BLOCKSTAMP
    sig = SIGNATURE
    expires_on = MedianTime + sigValidity
    chainable_on = MedianTime + sigPeriod
    replayable_on = MedianTime + sigReplay
    expired_on = 0
)

```

Qu’il s’agisse d’une nouvelle certification ou d’un renouvellement, dans tous les cas c’est “une certification” et donc l’entrée est identique.

> [@elois](#):
>
> or certaines lignes d’index concernent le passé, donc sans REDUCE\_BY on compte les certifications expirées.

Oui, et c’est ça le bug dans la méthode `findByReceiverAndExpiredOn()`. Plus précisément, le comportement alterne :

- parfois les certifications expirées sont comptées (cas conforme à la v11 du protocole)
- parfois les certifications expirées ne sont pas comptées à cause de l’élagage automatique (car l’élagage est une réduction !)

Pour résumer il y avait bien 2 bugs ici :

- bug#1 : l’entrée de GerardSiegle avec 4 certifications, bug non bloquant pour la Ğ1 mais problème vis-à-vis de la licence
- bug#2 : l’erreur de résolution de fork qui pour le coup est bloquante pour la Ğ1 et dont l’origine est double :
  - l’absence de réduction dans le protocole pour cette règle BR\_G27 qui n’est clairement pas cohérente avec la philosophie générale des index
  - une réduction automatique par Duniter qui est en conflit avec l’absence de réduction de BR\_G27

---

<div class="post-metadata">

### Author: ![cgeek](https://forum.duniter.org/user_avatar/forum.duniter.org/cgeek/32/279_2.png) [@cgeek](https://forum.duniter.org/u/cgeek)
#### Post date: [12 January 2020 16:26 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/37 "2020-01-12T16:26:41Z")

</div>

> [@cgeek](#):
>
> une réduction automatique par Duniter qui est en conflit avec l’absence de réduction de BR\_G27

Eh bien en fait c’était plus subtil. La réduction automatique n’était pas en cause car au final elle ne supprimait rien dans le CINDEX.

Non, en fait c’est le _dépilement de bloc_ ([bug#1396](https://git.duniter.org/nodes/typescript/duniter/issues/1396)) : lors d’une résolution de fork, Duniter dépile les blocs pour annuler les modifications introduites par eux.

Or, dans le cas de certifications renouvelées avant terme Duniter _supprimait_ le lien existant entre l’émetteur et le receveur, alors que pourtant ce lien existe toujours puisque même si le renouvellement est supprimé, l’ancienne certification est bien entendu toujours valable !

De ce fait pour GerardSiegle si nous rejouons la situation : état au bloc #284604 :

```
duniter sync g1.cgeek.fr 284604

```

```auto
┌─────┬────────┬──────────────────┬────────────┬─────────────────┬────────────┬────────────┬──────────────┬───────────────┐
│ row │ op │ issuer │ created_on │ written_on │ expires_on │ expired_on │ chainable_on │ replayable_on │
│ 0 │ CREATE │ CharlesAbecassis │ 96364 │ 96857-000000408 │ 1582171975 │ 0 │ 1519634701 │ 1524462301 │
│ 1 │ CREATE │ loanblanchard │ 103654 │ 106456-000001A4 │ 1584427318 │ 0 │ 1522609561 │ 1527437161 │
└─────┴────────┴──────────────────┴────────────┴─────────────────┴────────────┴────────────┴──────────────┴───────────────┘

```

Puis, on applique le bloc qui contient les certifications _dont 1 renouvellement de CharlesAbecassis_ :

```
duniter pull g1.cgeek.fr 284605

```

```auto
┌─────┬────────┬──────────────────┬────────────┬─────────────────┬────────────┬────────────┬──────────────┬───────────────┐
│ row │ op │ issuer │ created_on │ written_on │ expires_on │ expired_on │ chainable_on │ replayable_on │
│ 0 │ CREATE │ CharlesAbecassis │ 96364 │ 96857-000000408 │ 1582171975 │ 0 │ 1519634701 │ 1524462301 │
│ 1 │ CREATE │ loanblanchard │ 103654 │ 106456-000001A4 │ 1584427318 │ 0 │ 1522609561 │ 1527437161 │
│ 2 │ CREATE │ AlainLebrun │ 284266 │ 284605-000001A7 │ 1640737001 │ 0 │ 1578165360 │ 1582992960 │
│ 3 │ CREATE │ CharlesAbecassis │ 278986 │ 284605-000001A7 │ 1639117359 │ 0 │ 1578165360 │ 1582992960 │
│ 4 │ CREATE │ AnneAmbles │ 282287 │ 284605-000001A7 │ 1640145167 │ 0 │ 1578165360 │ 1582992960 │
└─────┴────────┴──────────────────┴────────────┴─────────────────┴────────────┴────────────┴──────────────┴───────────────┘

```

Jusque-là “tout va bien” : CharlesAbecassis a bien sa certification comptée en double par Duniter : c’est conforme au protocole v11 (mais pas à la licence).

Si je revert le bloc :

```
duniter revert 1

```

Alors _au moment de l’exécution de la règle BR\_G27_, Duniter voit :

```auto
┌─────┬────────┬──────────────────┬────────────┬─────────────────┬────────────┬────────────┬──────────────┬───────────────┐
│ row │ op │ issuer │ created_on │ written_on │ expires_on │ expired_on │ chainable_on │ replayable_on │
│ 0 │ CREATE │ loanblanchard │ 103654 │ 106456-000001A4 │ 1584427318 │ 0 │ 1522609561 │ 1527437161 │
└─────┴────────┴──────────────────┴────────────┴─────────────────┴────────────┴────────────┴──────────────┴───────────────┘

```

En effet le `revert` a **supprimé** le lien existant entre GerardSiegle et CharlesAbecassis 😕. Pourtant le CINDEX affiché est toujours bon, mais c’est en interne que la BDD est incohérente.

## Conséquences

Comme indiqué dans le ticket du [bug#1396](https://git.duniter.org/nodes/typescript/duniter/issues/1396) :

- **Conséquence 1** : BR\_G27 : les forks qui dépilent des renouvellements anticipés de certification créent potentiellement une situation de rejet d’un bloc pourtant accepté précédemment dans lequel un utilisateur pourtant légitime à entrer (relativement au protocole v11). Ce rejet dépend de la situation du membre par rapport à la limite des 5 certifications.
- **Conséquence 2** : BR\_G95 : les forks qui dépilent des renouvellements anticipés de certification peuvent exclure à tort des membres trop proches de la limite des 5 certifications.

Il n’est pas du tout exclu que cela se soit déjà produit.

À noter enfin que la règle de distance n’est pas affectée par cette anomalie, les liens sont toujours bien présents dans le module de calcul de WoT.

## Correctif

Le correctif viendra cette semaine, avec le test automatisé de verrou. Il m’a déjà fallu un dimanche entier pour débusquer l’anomalie à cause d’une fausse piste, je suppose qu’il me faudra une autre journée pour commiter le correctif + test + commandes de débogage qui m’ont aidé (notamment celle qui vous affiche ces beaux tableaux d’INDEX).

---

<div class="post-metadata">

### Author: ![Inso](https://forum.duniter.org/user_avatar/forum.duniter.org/inso/32/1229_2.png) [@Inso](https://forum.duniter.org/u/Inso)
#### Post date: [12 January 2020 18:27 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/38 "2020-01-12T18:27:33Z")

</div>

Merci beaucoup pour le temps que tu continues de prendre pour Duniter en tout cas. Il était plutôt costaud celui ci ! Un dimanche complet passé a analyser un bug ça fait jamais plaisir 🙂 J’espère que ton analyse permettra a d’autres développeurs de tenter le correctif la prochaine fois !

---

<div class="post-metadata">

### Author: ![cgeek](https://forum.duniter.org/user_avatar/forum.duniter.org/cgeek/32/279_2.png) [@cgeek](https://forum.duniter.org/u/cgeek)
#### Post date: [12 January 2020 18:44 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/39 "2020-01-12T18:44:33Z")

</div>

La couche d’accès aux données c’est vraiment pas le plus facile. Qu’en penses-tu @elois, toi qui viens de refondre celle de Dunitrust ?

---

<div class="post-metadata">

### Author: ![elois](https://forum.duniter.org/user_avatar/forum.duniter.org/elois/32/1541_2.png) [@elois](https://forum.duniter.org/u/elois)
#### Post date: [12 January 2020 18:51 UTC](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712/40 "2020-01-12T18:51:36Z")

</div>

> [@cgeek](#):
>
> Qu’en penses-tu @elois, toi qui viens de refondre celle de Dunitrust ?

Perso je trouve que la difficulté n’est pas la couche d’accès aux données mais le revert d’un bloc.  
C’est très délicat d’appliquer un bloc a l’envers et ça peut entraîner des anomalies très difficilement décelables, j’ai déjà eu une anomalie sur Dunitrust a cause d’un bout de code dans le revert d’un bloc.

Peut-être qu’il serait pertinent de spécifier dans le protocole l’algo de revert afin qu’on s’assure que la manière de revert respecte l’état des index du protocole 🙂

[Previous page](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712.md?page=1)

[Next page](https://forum.duniter.org/t/ancien-membre-de-retour-avec-seulement-4-certifications/6712.md?page=3)
