Actualités du développement Safe 🇫🇷 30 septembre 2021

Ceci est une traduction automatique. L’original en anglais est ici: Update 30 September, 2021

Comme nous l’avons mentionné il y a quelques semaines, l’ancien type de données Sequence pour les données mutables a été remplacé par Register. Les registres peuvent faire tout ce que Sequence pourrait en termes de stockage des versions précédentes avec l’avantage supplémentaire qu’il peut également gérer la concurrence. Cette semaine, David Rusu lève le voile sur le monde mystérieux de Merkle Registers.

Progrès général

David Rusu a pratiquement terminé les fonctionnalités de base pour le client qui écrit le Spentbook. Une fois qu’il est complètement en place, la tâche de la Monnaie sera en lecture seule : la Monnaie n’aura qu’à vérifier le Spentbook pour les engagements de transaction DBC pour vérifier que toutes les entrées sont engagées dans la même transaction et valider les soldes de transaction.

@Chris.connelly continue de lutter avec qp2p. La plupart des tâches qu’il effectue concernant les messages entrants sont probablement obsolètes maintenant que nous n’utilisons plus le pool de connexions pour garder les connexions ouvertes, et le fait d’amener les connexions et la gestion des messages entrants dans le référentiel safe_network devrait améliorer la stabilité. C’est un peu de boulot quand même !

Chris a également identifié un bug de longue date dans les tests qp2p, qui est maintenant corrigé.

@lionel.faber se concentre sur les outils CI/CD et de lancement et a mis à jour les outils d’automatisation pour s’appuyer sur une machine virtuelle cloud pour lancer un testnet à part entière. Tout le monde peut utiliser cet outil, à condition de disposer des informations d’identification requises pour AWS et Digital Ocean. L’outil est configurable et peut être déclenché selon les besoins. En interne, nous utilisons des déclencheurs manuels et un commentaire spécial « launch-testnet » dans les revues de relations publiques.

Les travaux sur la CLI et l’API se poursuivent pour les rendre compatibles avec la dernière version de safe_network … ça y arrive, mais comme @Chriso mentionné mardi, il y a encore des gremlins qui rongent les câbles, y compris des problèmes liés à la récupération de fichiers avec la CLI.

Nous avons mis en place des assertions de base de journal testnet, ce qui devrait nous aider à nous assurer que nous ne bouclons plus les messages (et en fait, nous avons déjà détecté une amplification mineure des messages). Ce n’est toujours pas fusionné car nous continuons à pirater les cas de stabilité.

Cette semaine, nous avons réorganisé les tentatives des clients pour qu’elles soient plus saines, ce qui a aidé ; nous avons écrasé certaines fausses erreurs produites occasionnellement, ce qui était dû au fait que nous nous appuyions sur des erreurs tokio (lorsque la tâche elle-même s’était bien terminée). Et @yogesh a commencé à améliorer l’amorçage du client sur le réseau, qui va actuellement pour tout nœud joignable, mais n’essaie pas d’établir l’état du réseau, ce qui conduit plus tard à plus de messages AE que nécessaire.

Merkle Registre

Cette semaine, nous aimerions approfondir le Merkle Register, l’un des deux types de données primitifs du Safe Network (l’autre étant des morceaux immuables).

Le registre Merkle est un nouveau CRDT que nous avons mis au point pour modéliser l’état mutable dans le réseau sécurisé, il prend en charge les écritures simultanées et la traversée de l’historique. Ils sont largement utilisés dans NRS pour maintenir les mappages de noms, utilisés pour suivre les versions d’un ou de plusieurs fichiers et de toute application nécessitant un état mutable.

La famille Registre CRDT

Les registres sont utilisés pour écrire et lire une valeur, pensez aux registres CPU. Les CRDT de registre existants sont le registre à valeurs multiples (MVReg) et le registre Last-Write-Wins (LWWReg). Notre registre Merkle (MerkleReg) est encore un autre CRDT dans cette famille.

Tous les registres suivent une API similaire.

# Vous pouvez lire la ou les valeurs actuelles stockées dans le registre
read(reg) -> val(s)

# Vous pouvez écrire une valeur dans un registre en utilisant un contexte causal
écrire (reg, val, ctx) -> reg

# Fusionner deux registres
merge(reg1, reg2) -> merge-reg

Le MerkleReg est construit sur un Merkle DAG. Le Merkle DAG est une généralisation sur l’arbre Merkle qui assouplit les nœuds pour avoir plusieurs parents et placer des données à chaque nœud.

Avec Merkle Trees, nous organisons les données au niveau des feuilles d’un arbre binaire et les hachons par paires pour obtenir le prochain niveau de nœuds, nous répétons cela en hachant des paires de ces hachages jusqu’à ce que nous atteignions la racine. C’est une structure de données incroyablement flexible, utilisée dans de nombreux systèmes décentralisés. Les DAG Merkle suppriment la restriction de l’arborescence binaire. Nous pouvons maintenant placer des données sur chaque nœud et chaque nœud peut avoir plusieurs parents.

La façon dont nous construisons le MerkleReg consiste à utiliser les racines du Merkle DAG comme valeurs de registre actuelles. Par exemple, considérons la série d’opérations suivante.

Commençons par lire le DAG vide, nous récupérons l’ensemble vide.

lire(∅) = {}

Écrivez « a » dans le registre, nous utilisons l’ensemble vide comme contexte.

                  ??
écrire(∅, a, {}) = |
                  une

Simultanément, un autre client écrit dans le même registre.

                  ??
écrire(∅, b, {}) = |
                  b

Une fois que les deux clients poussent leur état vers le haut, nous pouvons fusionner les deux registres concurrents.

fusionner(|, |) = / \
      un b un b

La lecture du registre fusionné restitue les deux valeurs concurrentes.

       ??
lire( / \ ) = {a, b}
     un B

Nous pouvons maintenant résoudre les valeurs concurrentes en utilisant à la fois a et b comme contexte d’écriture.

                            ??
        / \
écrire( / \ , c, {a, b}) = a b
      un B                \ /
                            c

La lecture du registre final ne renvoie que « c ».

        ??
       / \
lire( a b ) = {c}
       \ /
        c

Maintenant, une propriété intéressante de ce MerkleReg par rapport à certains des autres CRDT de registre est que nous avons l’historique complet des branchements du registre maintenu dans le Merkle DAG. Si nous suivons un document, nous pouvons parcourir son historique pour voir comment il a évolué.

MultiSets et MultiMaps

Nous pouvons construire des MultiSets et des MultiMaps sur Merkle Registers tout simplement en tirant parti du fonctionnement des contextes d’écriture.

Les entrées écrites dans le registre avec un contexte vide apparaîtront lorsque nous relirons les valeurs, cela simule un Set CRDT.

Commencez par le registre vide.

lire(∅) = {}

Après avoir écrit y avec un contexte vide.

      ??
lire( | ) = {y}
      oui

Ensuite, écrivez x avec un contexte vide.

        ??
lire( / \ ) = {x, y}
      x y

Écriture de « z » avec un contexte vide.

         ??
lire( / | \ ) = {x, y, z}
      x yz

Nous pouvons maintenant simuler des suppressions en attribuant un nœud « corbeille » spécial :

        ??
lire( / | \ ) = {x, y, }
     x y

Fusionnez y avec :wastebasket: pour le supprimer.

        ??
lire( / | \ ) = {x, }
     x y
         \ /
          ??

Cela nous donne un Set CRDT avec des inserts et des retraits. Pour obtenir une carte CRDT, nous faisons des membres de l’ensemble une clé à 2 tuples : valeur :

          ??
lire( / | \ ) = {x:1, y:2, }
     x:1 y:2

La mise à jour de la valeur de « x » est effectuée en utilisant les entrées « x » actuelles en tant qu’enfants :
Ici, nous mettons à jour « x » pour stocker « 2 » au lieu de « 1 »

          ??
lire( / | \ ) = {x:2, y:2, }
     x:1 y:2
      |
     x:2

Comme il s’agit d’une structure éditée simultanément, nous pouvons nous retrouver avec plusieurs valeurs écrites pour une clé (d’où le multi dans Multi-Map) :

Un autre client écrit simultanément x:3

          ??
       / | \
lire( x:1 x:3 ) = {x:2, x:3, }
       |
      x:2

Ces entrées multiples peuvent être résolues en réécrivant une entrée pour x avec à la fois x:2 et x:3 comme enfants.

          ??
        / | \
lire( x:1 x:3 ) = {x:3, 🗑}
       | |
      x:2 |
        \ /
        x:3

Cela nous donne un CRDT MultiMap avec historique et fusion des valeurs concurrentes !

Implications du MerkleReg

Le MerkleReg remplace l’ancien type de données Sequence, nous avons constaté qu’essayer de modéliser des séquences linéaires dans un réseau partiellement ordonné n’allait pas avoir une sémantique propre. Au lieu de cela, nous adoptons les forks, le résultat est que les applications doivent gérer des valeurs concurrentes. Par exemple, un navigateur construit sur le réseau sécurisé doit gérer la possibilité qu’un site Web ait plusieurs pages index.html simultanées. NRS devra gérer plusieurs entrées pour le même nom.

Ce n’est pas un problème aussi grave qu’on pourrait le penser, la plupart des systèmes à grande échelle fonctionnent déjà avec ce modèle. Par exemple, le DNS permet plusieurs adresses IP associées à un domaine, et les choses (généralement) fonctionnent toujours.


Liens utiles

N’hésitez pas à répondre ci-dessous avec des liens vers les traductions de cette mise à jour de développement et les modérateurs les ajouteront ici.

En tant que projet open source, nous sommes toujours à la recherche de commentaires, de commentaires et de contributions de la communauté. Ne soyez donc pas timide, rejoignez-nous et créons ensemble le réseau sécurisé!