Prototype de GVA

Et du coup, je vois que tu as fait le changement pour mettre endpoints dans network.
aurais-tu le commit de ce changement que je vois comment tu as fait ?

Merci !

network_db.peers_old().iter(.., |it| {
Je vois à plusieurs endroits peers_old. Pourquoi old ?

Pour différencier de la future collection peers qui stockera le nouveau format de fiches de peer, notamment sans les peer partagés et sans les champs obsolètes.

1 Like

Ca s’annonce bien tout ca ! :slight_smile:

2 Likes

Ajout du champ receivedTime pour les transactions en mempool: il s’agit de la date et heure de première réception du document transaction par le nœud Duniter.

À la demande de @kimamila, cette information à également été ajoutée dans BMA, dans le champ time, ce champ valait null pour les transactions en attente, il contiendra désormais la date de réception du document :slight_smile:

À noter que le champ time contenait déjà la date d’écriture en blockchain pour les transactions écrites en blockchain.

Il semblerait que le code de Cesium n’est même pas besoin d’être modifié, car la date et heure de la transaction est le résultat de l’expression time || blockstampTime

Quant à GVA, il y a déjà depuis plusieurs mois le champ writtenTime pour les transactions en blockchain :wink:

Aujourd’hui j’ai réalisé quelques tests de ce nouveau champ receivedTime et il semble fonctionner. J’ai également testé la bonne valorisation du champ time dans BMA pour les transactions en attentes, là aussi ça semble bien fonctionner :smiley:

6 Likes

Énorme !
Ça veut dire qu’on va pouvoir s’appuyer sur des blocs plus ancien pour émettre les TX, et limiter au maximum les risques de pertes de TX a cause de fork. :slight_smile:

La prochaine version de Cesium va être sympa (commentaires chiffrés, scan réseau en tâche de fond, TX lié au bloc HEAD - 100) !
Faut juste que je trouve du temps pour la finir :slight_smile: mais notre bébé va mieux (après des soucis les premiers mois). Je vais pouvoir sortir la tête de l’eau.

5 Likes

Je suppose que c’est une typo : written time

1 Like

Une requête importante pour plein d’outils est les certifications (liste des certifications d’une identité et toutes les certifications).

@elois penses-tu que je peux m’en occuper ? Il me semble que tous les ingrédients sont là. :man_cook:

Je pense ajouter des champs issued et received à GvaIdtyDbV1. (ou issued_certs ou certs_issued, j’hésite toujours entre l’avantage du préfixage et le respect de la grammaire anglaise)

1 Like

Oui tu as les compétences pour. Par contre il faut qu’on prenne bien le temps de réfléchir à quel schéma de DB, et pour cela il faut partir du besoin. Je te propose de commencer par écrire les requêtes graphql que le client doit pouvoir faire, en précisant bien quelles données il doit pouvoir obtenir.

C’est seulement à partir d’une description non-ambigue du besoin qu’on pourra réfléchir à un schéma de DB optimisé pour ce besoin :slight_smile:

1 Like

Des outils comme la wotmap et la worldwotmap ont besoin de la liste de toutes les certifications actives :

query {
  certifications() {
    issuer # pubkey
    receiver # pubkey
  }
}

Des clients comme Cesium ont besoin des certifications d’une identité, avec leur numéro de bloc d’écriture, et date d’écriture ou date d’expiration :

query {
  certificationsOfIdty(pubkey: String) {
    issued {
      recipient # pubkey
      block_number # ou blockstamp ?
      written_time # ou expire_time, ou les deux
    }
    received {
      issuer # pubkey
      block_number # ou blockstamp ?
      written_time # ou expire_time, ou les deux
    }
  }
}

Les différents moyens que je vois :

  • ajouter des champs issued et received dans GvaIdtyDbV1, contenant la liste des certifications. Il faudrait juste les ajouter dans la requête idty et créer une requête paginée idties.
  • pareil, mais en stockant non pas les certifications, mais leur hash. Les certifications seraient stockées dans une autre db, par hash.

Comme il faut pouvoir retrouver les certifications d’une identité, je ne vois pas comment faire autrement sans refaire un index par clé publique, et dans ce cas-là on peut utiliser gva_identities.

Avoir les certifications avec les identités rend aussi les choses plus simples pour wotmap et worldwotmap.

2 Likes

Ok donc on doit pouvoir :

  • Parcourir toutes les certifications
  • Parcourir toutes les certifications émises par une clé publique donnée
  • Parcourir toutes les certifications reçues par une clé publique donnée
  • Pour chaque certification, avoir comme information: émétteur, receveur, numéro de bloc de création, numéro de bloc d’écriture (toutes dates pouvant être récupérées où calculer à partir de ces données).

De plus, il faut penser aux besoins d’indexation et de revert. On doit donc pouvoir mettre à jour une certification (renouvellement) sans en créer une nouvelle. On doit également pouvoir supprimer une certification lorsqu’elle expire (car cet event n’est pas déclaré dans les blocs).

En vue de ces besoins, voici comment je modifierai la DB :

  1. Ajouter une collection certifications dont la clé est issuer || target et la valeur une struct du genre:
GvaCertDbV1 {
  created_on: BlockNumber
  written_block: BlockNumber
}
  1. Ajouter une collection certs_by_expire avec comme clé U64BE et comme valeur Vec<(Pubkey, Pubkey)>
  2. Ajouter un champ certifiers: Vec<Pubkey> à la struct GvaIdtyDbV1.

Et c’est tout, je te laisse réfléchir à pourquoi c’est suffisant pour répondre correctement à tous les cas :wink:

Pour gagner de la place on peut remplacer la clé par un id en u64, sled permet de générer un id garanti unique, il faut juste que je ré-expose cette fonction :slight_smile:

Au lieu d’avoir 6 clés publiques par certification on aurait alors 4 id et 2 clés publiques. Soit 4 x 8 + 2 x 33 = 96 octets par certification au lieu de 5 x 33 = 165 octets par certification.

Ce qui donne :

  1. Ajouter une collection certifications dont la clé est U64BE et la valeur une struct du genre:
GvaCertDbV1 {
  issuer: Pubkey,
  receiver: Pubkey,
  created_on: BlockNumber,
  written_block: BlockNumber,
}
  1. Ajouter une collection certs_by_expire avec comme clé U64BE et comme valeur Vec<u64>
  2. Ajouter les 2 champs certifiers: Vec<u64> et certified: Vec<u64> à la struct GvaIdtyDbV1.

Ok, juste une question : pourquoi certs_by_expire ? pour WotWizard ?

Edit: ou c’est parce que l’expiration de la certification n’est pas dans le bloc ?

donc pour ajouter une certification, il faut d’abord vérifier en parcourant les certifications listées dans le champ certified de l’issuer qu’il n’en existe pas une ayant les mêmes issuer et receiver ; si oui, la modifier, si non, la créer.

Oui c’est ça, je l’ai dit plus haut :

Exactement, bien vu :slight_smile:

Donc le champ certified ne sera pas un Vec mais un HashSet :slight_smile:

1 Like

Un HashSet<PublicKey> alors ? certifiers restant un Vec d’IDs de certifications ?

1 Like

Bien vu, on a donc 3 id et 3 clés publiques donc 121 octets au lieu de 165 sans id, on est toujours gagnant avec id :slight_smile:

1 Like

Ah, par contre il faut pouvoir retrouver la certification, donc plutôt certified: HashMap<PublicKey, u64>

Bien vu encore, donc là ça commence à sentir le roussi, c’est le signe qu’il faut changer de stratégie.

En fait je pense qu’on doit plutôt associer un nombre entier unique à chaque identité, c’est déjà ce que fait le module wotb avec le wotb_id (un u32).

Ça implique de stocker quelque part le nombre d’identités qui ont été créées mais ce serait bien plus propre.

Ainsi la collection certifications pourrait avoir pour clé un (u32, u32).

On aurait donc:

  1. Ajout collection certifications clé (u32, u32) valeur GvaCert { created_on: BlockNumber, written_on: BlockNumber }
  2. Ajout 2 champs id: u32 et certifiers: Vec<u32> à la struct GvaIdtyDbV1.
  3. Ajout collection certs_by_expire clé U64BE valeur Vec<(u32, u32)>

Ça nous ferait une empreinte de 20 octets par certif (je compte que id et pubkey) au lieu de 121 ou 165. En contrepartie on se prendrait 8 octets de plus par identité mais comme il y a par construction beaucoup plus de certifications que d’identité on est vraiment ultra gagnant niveau place avec cette nouvelle approche :smiley:

J’expérimente la réflexion en public sur le schéma de la DB, d’habitude j’y réfléchis seul, et la seule fois ou @tuxmain a modifié la DB on a eu cette réflexion en discussion privée. Je pense qu’on doit perdre à peu près tout le monde mais bon :slight_smile:

2 Likes

Ah, un nouvel obstacle apparaît : quand une certification expire, il faut pouvoir mettre à jour le certifiers de l’identité certifiée… donc il faut une collection idties_by_id ou mettre la pubkey du certifié dans GvaCertDbV1. :sweat_smile:

Aussi, comment l’indexeur récupère la durée de validité d’une certification ? Et l’expiration arrive quand HEAD.median_time > created_time + sig_validity, ou alors c’est written_time + sig_window ? ou les deux ?

Edit: nouveau problème, pour le revert :

  • du renouvellement d’une certification, comment on retrouve l’ancienne ?
  • de l’expiration d’une certification, comment on la retrouve ?

cindex stocke encore les certifications expirées, avec un champ expired_on, ce doit être pour ça. On peut donc ajouter un champ expired_on à GvaCertDbV1.

Reste à retrouver la certification avant renouvellement. Avec un champ last_written_on, pour pouvoir la retrouver dans l’index des blocs, et written_on resterait la valeur pour la première certification ?

Et pour éviter de s’encombrer avec trop de certifications expirées, on peut dans un second temps supprimer celles datant d’avant la fenêtre de fork.

C’est vachement compliqué en fait ! :face_with_head_bandage: