Artículo del Blog

Horizon acaba de mejorar mucho: nuestro nuevo motor de ingestión y otras cosas geniales

Autor

Stellar Development Foundation

Fecha de publicación

Horizonte

Ingestión

API

Hace más de un año, el equipo de StellarX añadió un GitHub problema sobre un extraño 500 Internal Server Error devuelto por Horizon de vez en cuando. Después de revisarlo, nos dimos cuenta de la causa: Horizon estaba obteniendo ofertas de la base de datos de Stellar-Core y algunas de esas ofertas venían de libros contables aún no ingeridos por Horizon. Para obtener un tiempo de creación para las ofertas, Horizon verifica el tiempo de cierre del libro contable, y si un libro contable aún no ha sido ingerido, esa verificación resulta vacía. De ahí el error del servidor.

Mientras tanto, recibíamos informes sobre tiempos de respuesta muy largos para el endpoint /paths. Stellar tiene un libro de órdenes descentralizado que permite a los usuarios intercambiar un activo por otro, y el endpoint /paths te ayuda a encontrar el mejor conjunto de intercambios intermedios para que puedas cambiar la cantidad mínima posible del activo fuente por la cantidad máxima posible del activo destino. Horizon dependía de la base de datos de Stellar-Core, que simplemente no está optimizada para consultas de búsqueda de caminos.

Esos problemas (principalmente menores) no eran exactamente nuevos — habíamos sido conscientes de problemas similares durante años — pero se estaban volviendo cada vez más comunes. Para abordarlos, tuvimos que hacer un cambio fundamental en la arquitectura de Horizon, y construir un sistema completamente nuevo para la ingestión de datos. En los últimos meses, eso es exactamente lo que hemos hecho.

El nuevo sistema de ingestión, que está incluido en la versión Horizon v0.20.1, está listo para pruebas, y en este breve blog explicaré el razonamiento detrás de ello y describiré dos características experimentales en Horizon que no habrían sido posibles en el antiguo sistema. Tiene algunas grandes ventajas sobre el antiguo sistema de ingestión — es más consistente y amigable para los desarrolladores, permite la configuración por parte del usuario, y no sobrecarga a Stellar-Core — y eventualmente planeamos pasarnos completamente a él. En este momento, ambos sistemas están trabajando concurrentemente, y si habilitas una bandera de característica especial en Horizon puedes probar el nuevo sistema y sus nuevas características ¡ahora mismo!

El nuevo paquete de ingestión Golang también puede ser utilizado fuera de Horizon para construir aplicaciones y servicios personalizados. En los próximos meses, publicaremos documentación, ejemplos y una nueva entrada de blog explicando cómo usarlo.

Entradas y transacciones de libro contable

Comencemos con una explicación extremadamente breve y simplificada de cómo funciona Stellar-Core. En resumen: Stellar-Core es una máquina de estado replicada. Cada libro contable representa un estado que es cambiado por un conjunto de transacciones. Stellar-Core luego propaga la información sobre el nuevo estado/libro contable a la red y publica un punto de control en los archivos de historia cada 64 libros contables.

Fuente: stellar.org/developers/stellar-core/software/core-data-flow.pdf

Podemos ver que hay dos tipos de datos conectados a cada libro contable:

  • Estado que en Stellar son entradas de libro contable: cuentas, líneas de confianza, ofertas, datos de cuenta.
  • Transiciones que en Stellar son transacciones con operaciones modificando entradas de libro contable. Un pago, por ejemplo, es una transición entre dos estados de saldo de cuenta.

Antes del nuevo sistema de ingestión, Horizon no tenía su propia vista del estado (o entradas de libro contable). Los usuarios podían solicitar los datos históricos (transacciones, operaciones, pagos, intercambios, etc.), y Horizon los serviría desde su DB directamente, pero todas las solicitudes conectadas al estado actual del libro contable se reenviaban a Stellar-Core.

Esta única decisión arquitectónica causó muchos problemas, entre ellos:

  • Horizon dependía del esquema de base de datos de Stellar-Core, que no estaba optimizado para los casos de uso de Horizon. Campos codificados en XDR y la falta de índices hacían que algunas consultas fueran lentas o imposibles.
  • Alta carga en Stellar-Core. Si las consultas no estaban optimizadas, o simplemente había demasiadas de ellas, la base de datos de Stellar-Core se ralentizaría y, en el peor de los casos, perdería el seguimiento del consenso, que es crítico para el correcto funcionamiento de la red.
  • Los datos eran potencialmente inconsistentes. Stellar-Core y Horizon son dos sistemas diferentes. Era posible que Stellar-Core hubiera cerrado el libro contable X pero Horizon todavía estaba ingiriendo el libro contable X-1. Eso es lo que causó el problema de StellarX mencionado al principio de este artículo.

Para solucionar estos problemas, el nuevo sistema de ingestión tiene una copia completa del estado del libro contable construida usando archivos de historia. Usar archivos de historia no genera carga en Stellar-Core, y permite construir el estado no solo para el último libro contable sino también para cualquier otro libro de control en el pasado. Tener acceso al estado permite la creación de nuevas características, como los dos ejemplos que se encuentran a continuación.

Cuentas para Firmante

“Cuentas para Firmantes” fue una solicitud de característica muy popular en nuestro GitHub. Puedes usarlo para buscar todas las cuentas que coinciden con un firmante dado, lo que facilita a los clientes de Stellar implementar multi-firma de manera amigable para el usuario. Si, por ejemplo, tienes una cuenta principal que también co-firma varias cuentas multi-firma — una cuenta de negocios, una cuenta que compartes con tu pareja, una cuenta de confianza familiar — tu billetera Stellar puede encontrarlas todas usando tu cuenta principal, sin esfuerzo adicional de tu parte. Con una sola llave, puedes gestionar fácilmente múltiples cuentas multi-firma.

Antes del nuevo sistema de ingestión, no podíamos construir la vista “Cuentas para Firmantes” porque Stellar-Core no tiene un índice en el campo firmante en la tabla de firmantes, y la consulta no era lo suficientemente rápida para un uso en tiempo real, en producción. Para complicar más las cosas, una versión posterior de Stellar-Core añadió una actualización de rendimiento que eliminó completamente la tabla de firmantes y movió el array codificado en XDR de firmantes a la tabla de cuentas.

Debido a que el nuevo sistema puede recrear el estado, pudimos crear una tabla en la base de datos de Horizon con todos los firmantes e índices adecuados. Esta característica ha estado disponible desde 0.19.0, pero está oculta detrás de una bandera de característica. También puedes probarlo en nuestros clusters públicos de Horizon.[@portabletext/react] Unknown block type "span", specify a component for it in the `components.types` prop[@portabletext/react] Unknown block type "span", specify a component for it in the `components.types` prop

Búsqueda de Caminos

Otra característica que lanzamos como parte de 0.20.0 es un algoritmo de búsqueda de caminos más rápido. Hubo muchos experimentos pasados que intentaron mejorar el rendimiento de la búsqueda de caminos a través de Horizon. El nuevo sistema de ingestión finalmente añade estas mejoras a Horizon.

La versión anterior del algoritmo de búsqueda de caminos era lenta por dos razones:

  • Estaba utilizando una base de datos al encontrar caminos expandiéndolos con nuevos activos. El tiempo de ida y vuelta requerido para expandir cada camino único hacía esto muy lento para algunas consultas.
  • Estaba utilizando la base de datos de Stellar-Core, que no está diseñada para este caso de uso específico.

Para mejorar la búsqueda de caminos, usamos el nuevo sistema de ingestión para construir un grafo de libro de órdenes en memoria de todas las ofertas en la red. Como mantenemos todo en memoria, el acceso a los datos es extremadamente rápido. Esto disminuyó el tiempo de respuesta del endpoint /paths para algunas consultas ¡en 10 veces! Para probarlo, inicia Horizon con la bandera de característica ENABLE_EXPERIMENTAL_INGESTION=true bandera de función o usa nuestros clústeres públicos de Horizon. Para más información, consulta el notas de lanzamiento.

Tiempo máximo de respuesta para el endpoint /paths en el clúster de SDF. La nueva versión se implementó el 2019–08–26.

¿Qué sigue?

En el tercer trimestre de 2019 trabajaremos en trasladar todas las características de Horizon al nuevo sistema. También publicaremos documentación para el nuevo paquete de ingestión que se puede utilizar para construir aplicaciones y servicios personalizados y avanzados sin Horizon.