Actualización de Safe Network Dev 🇪🇸 30 de septiembre de 2021

Esta es una traducción automática. El original en inglés está aquí: Update 30 September, 2021

Como mencionamos hace unas semanas, el antiguo tipo de datos Sequence para datos mutables fue reemplazado por Register. Los registros pueden hacer todo lo que Sequence podría en términos de almacenar versiones anteriores con la ventaja adicional de que también puede manejar la concurrencia. Esta semana, David Rusu abre la tapa del misterioso mundo de Merkle Registers.

Progreso general

David Rusu prácticamente ha completado la funcionalidad básica para el cliente que escribe el Spentbook. Una vez que esté completamente en su lugar, hará que la tarea de Mint sea de solo lectura: Mint solo necesitará verificar el Spentbook para los compromisos de transacción DBC para verificar que todas las entradas estén comprometidas con la misma transacción y validar los saldos de la transacción.

@Chris.connelly continúa luchando con qp2p. Muchos de los trabajos que hace relacionados con los mensajes entrantes probablemente estén obsoletos ahora que ya no usamos el grupo de conexiones para mantener las conexiones abiertas, y llevar las conexiones y el manejo de mensajes entrantes dentro del repositorio safe_network debería mejorar la estabilidad. ¡Aunque es un poco de trabajo!

Chris también identificó un error de larga data en las pruebas de qp2p, que ahora está corregido.

@lionel.faber se centra en CI / CD y herramientas de lanzamiento y actualizó las herramientas de automatización para construir en una VM en la nube para lanzar una red de prueba completa. Cualquiera puede utilizar esta herramienta, siempre que tenga las credenciales necesarias para AWS y Digital Ocean. La herramienta es configurable y se puede activar según sea necesario. Internamente, estamos utilizando activadores manuales y un comentario especial “launch-testnet” en las revisiones de relaciones públicas.

El trabajo en la CLI y la API continúa para hacerlos compatibles con la última versión de safe_network … está llegando, pero como @Chriso mencionado el martes todavía hay algunos gremlins royendo cables, incluidos algunos problemas relacionados con la recuperación de archivos con la CLI.

Hemos estado configurando algunas afirmaciones básicas de registro de testnet, que deberían ayudar a asegurarnos de que ya no estamos repitiendo mensajes (y, de hecho, ya hemos detectado una pequeña amplificación de mensajes). Esto todavía no se ha fusionado, ya que seguimos pirateando los casos de las esquinas de estabilidad.

Esta semana hemos reajustado los reintentos de los clientes para que estén más cuerdos, lo que ha ayudado; hemos eliminado algunos errores falsos que se producían ocasionalmente, lo que se debió a que confiamos en errores de tokio (cuando la tarea real se completó bien). Y @yogesh ha comenzado a mejorar el arranque del cliente a la red, que actualmente se aplica a cualquier nodo contactable, pero no intenta establecer el estado de la red, lo que luego conduce a más mensajes AE de los necesarios.

Registro de Merkle

Esta semana nos gustaría hacer una inmersión profunda en Merkle Register, uno de los dos tipos de datos primitivos en Safe Network (el otro son fragmentos inmutables).

Merkle Register es un nuevo CRDT que hemos creado para modelar el estado mutable en Safe Network, admite escrituras simultáneas y recorrido histórico. Se usan ampliamente en NRS para mantener asignaciones de nombres, se usan para rastrear versiones de un archivo (s) y cualquier aplicación que necesite un estado mutable.

La familia Register CRDT

Los registros se utilizan para escribir y leer un valor, piense en los registros de la CPU. Los CRDT de registro existentes son el registro de valores múltiples (MVReg) y el registro de ganancias de última escritura (LWWReg). Nuestro Merkle Register (MerkleReg) es otro CRDT en esta familia.

Todos los registros siguen una API similar.

# Puede leer los valores actuales almacenados en el registro
leer (reg) -> val (s)

# Puede escribir un valor en un registro usando un contexto causal
escribir (reg, val, ctx) -> reg

# Fusionar dos registros
fusionar (reg1, reg2) -> merged-reg

El MerkleReg está construido sobre un Merkle DAG. El Merkle DAG es una generalización del árbol Merkle que relaja los nodos para tener varios padres y colocar datos en cada nodo.

Con Merkle Trees, organizamos los datos en las hojas de un árbol binario y los dividimos en pares para obtener el siguiente nivel de nodos, repetimos esto mediante el hash de los pares de estos valores hash hasta llegar a la raíz. Es una estructura de datos increíblemente flexible, utilizada en muchos sistemas descentralizados. Merkle DAG elimina la restricción del árbol binario. Ahora podemos colocar datos en cada nodo y cada nodo puede tener varios padres.

La forma en que construimos MerkleReg es usar las raíces del Merkle DAG como los valores de registro actuales. Por ejemplo, considere la siguiente serie de operaciones.

Comience leyendo el DAG vacío, recuperamos el conjunto vacío.

leer (∅) = {}

Escriba a en el registro, usamos el conjunto vacío como contexto.

                  ∅
escribir (∅, a, {}) = |
                  a

Al mismo tiempo, otro cliente escribe en el mismo registro.

                  ∅
escribir (∅, b, {}) = |
                  B

Una vez que los dos clientes aumentan su estado, podemos fusionar los dos registros concurrentes.

fusionar (|, |) = / \
      a b a b

La lectura del registro combinado devuelve ambos valores concurrentes.

       ∅
leer (/ \) = {a, b}
     a b

Ahora podemos resolver los valores concurrentes usando tanto a como b como contexto de escritura.

                            ∅
        ∅ / \
escribir (/ \, c, {a, b}) = a b
      a b \ /
                            C

La lectura del registro final solo devuelve c.

        ∅
       / \
leer (a b) = {c}
       \ /
        C

Ahora bien, una buena propiedad de este MerkleReg en comparación con algunos de los otros CRDT de registro es que tenemos todo el historial de ramificaciones del registro mantenido en el Merkle DAG. Si estamos rastreando un documento, podemos recorrer su historial para ver cómo evolucionó.

MultiSets y MultiMaps

Podemos construir MultiSets y MultiMaps encima de Merkle Registers simplemente aprovechando cómo funcionan los contextos de escritura.

Las entradas escritas en el registro con un contexto vacío aparecerán cuando volvamos a leer los valores, esto simula un Set CRDT.

Comience con el registro vacío.

leer (∅) = {}

Después de escribir y con contexto vacío.

      ∅
leer (|) = {y}
      y

Luego, escribe x con contexto vacío.

        ∅
leer (/ \) = {x, y}
      x y

Escribiendo z con contexto vacío.

         ∅
leer (/ | \) = {x, y, z}
      x y z

Ahora podemos simular eliminaciones asignando un nodo especial “basura”:

        ∅
leer (/ | \) = {x, y, 🗑}
     x y 🗑

Fusionar y con :wastebasket: para eliminarlo.

        ∅
leer (/ | \) = {x, 🗑}
     x y 🗑
         \ /
          🗑

Eso nos da un conjunto CRDT con inserciones y eliminaciones. Para obtener un mapa CRDT, hacemos que los miembros del conjunto sean una clave de 2 tuplas: valor:

          ∅
leer (/ | \) = {x: 1, y: 2, 🗑}
     x: 1 y: 2 🗑

La actualización del valor de x se realiza mediante el uso de las entradas actuales de x como hijos:
Aquí actualizamos x para almacenar 2 en lugar de 1

          ∅
leer (/ | \) = {x: 2, y: 2, 🗑}
     x: 1 y: 2 🗑
      |
     x: 2

Dado que esta es una estructura editada al mismo tiempo, podemos terminar con varios valores escritos para una clave (de ahí el multi en Multi-Map):

Otro cliente escribe simultáneamente x: 3

          ∅
       / | \
leer (x: 1 x: 3 🗑) = {x: 2, x: 3, 🗑}
       |
      x: 2

Estas múltiples entradas se pueden resolver escribiendo una entrada para x con x: 2 y x: 3 como hijos.

          ∅
        / | \
leer (x: 1 x: 3 🗑) = {x: 3, 🗑}
       | |
      x: 2 |
        \ /
        x: 3

¡Esto nos da un CRDT MultiMap con historial y fusión de valores concurrentes!

Implicaciones de MerkleReg

MerkleReg reemplaza el antiguo tipo de datos Sequence, descubrimos que intentar modelar secuencias lineales en una red parcialmente ordenada no iba a tener una semántica limpia. En su lugar, adoptamos las bifurcaciones, el resultado es que las aplicaciones deben lidiar con valores concurrentes. Por ejemplo, un navegador integrado en la red segura debe afrontar la posibilidad de que un sitio web tenga varias páginas index.html simultáneas. NRS tendrá que lidiar con múltiples entradas para el mismo nombre.

Esto no es un problema tan grande como podría pensar, la mayoría de los sistemas a gran escala ya están trabajando con este modelo. Por ejemplo, DNS permite múltiples IP asociadas con un dominio, y las cosas (generalmente) aún funcionan.


Enlaces útiles

No dude en responder a continuación con enlaces a las traducciones de esta actualización para desarrolladores y los moderadores las agregarán aquí.

Como proyecto de código abierto, siempre estamos buscando retroalimentación, comentarios y contribuciones de la comunidad, así que no sea tímido, únase y creemos la red segura juntos.