La concurrencia en el modelo eUTxO no es un problema sino un desafío
En las semanas previas al inicio de la era Goguen, con el lanzamiento del Hard Fork Alonzo, se han presentado críticas al modelo eUTxO, diseñado por IOHK para Cardano.
En la testnet sucedió un problema de “concurrencia”, detectado por los desarrolladores de Minswap, quienes en una publicación en su blog, reconocen que el lanzamiento de la red de prueba pública no cumplió con las expectativas., argumentando que ser el primero no es fácil, pero era importante desplegar la plataforma DEX en la red de pruebas pública para empezar a recopilar datos e iterar en los diseños. Al fin y al cabo, ese es el objetivo de una red de pruebas.
En muchas transacciones, la plataforma devolvía la imposibilidad de procesarlas y había que intentarlo varias veces hasta que pudiera “encontrar su lugar en el bloque”:
La concurrencia
La concurrencia es la capacidad de diferentes partes o unidades de un programa, algoritmo, para ejecutarse fuera de orden o al mismo tiempo, con orden, sin afectar el resultado final. En el mundo de las criptomonedas, podemos entender mejor la concurrencia, especialmente cuando se trata de contratos inteligentes, como la capacidad de que varios agentes diferentes interactúen con el mismo contrato al mismo tiempo.
En el modelo UTxO se refiere a la cantidad de transacciones que se producen con demanda en un bloque, y desde una misma aplicación, por parte de los usuarios. Es decir, donde “concurren” varias operaciones que deben ser atendidas todas al mismo tiempo, y ordenadas en su ejecución.
El modelo de Cardano vuelve a las raíces de la industria, Bitcoin, pero con su creación del modelo UTXO extendido (eUTXO). Las salidas de dinero deja en saldo cero la dirección de envío y genera una nueva dirección para registrar el saldo no gastado (si queda saldo mayor a cero) de esa dirección de envío.
El modelo de contabilidad de Ethereum basado en account-balance admite solo una dirección por billetera, con operaciones en esa misma, a diferencia del modelo UTxO de Cardano, o también Bitcoin, admiten múltiples direcciones y con sus múltiples transacciones por billetera.
En el modelo de account-balance de Ethereum, el estado de cada bloque no se almacena en los bloques que se extraen, más bien se almacena en nodos localmente, que luego llegan a un acuerdo comparando ‘StateRoot’ — o el estado general del sistema.
La máquina virtual de Ethereum (EVM) interpreta las transacciones como eventos y determina el resultado de la transición de estado de estos eventos en función del estado anterior. Esto hace que la abstracción del desarrollador sea mucho más fácil y facilita la construcción de muchas DApps como Uniswap, AAVE, Curve.
Los contratos inteligentes, en sí mismos son concurrentes, pero el orden de transacciones real sigue siendo secuencial y no concurrente. Lo que esto significa es que, si bien Alice, Bob y Eve pueden estar accediendo a un DEX para intercambiar pares de tokens, el minero aún ordenará secuencialmente sus transacciones individuales mientras empaquetan todas estas transacciones en bloques. Luego, esos bloques se agregan a la cadena de bloques de Ethereum y luego los validadores los vuelven a ejecutar para garantizar que las transacciones sean realmente correctas.
¿Pueden las transacciones de Cardano ser concurrentes?
Esto ahora nos lleva al problema actual que crea un motivo de preocupación entre muchos desarrolladores de Plutus, el problema ‘Contrato-Concurrencia’. Esta concurrencia es diferente de la concurrencia de Ethereum, ya que actualmente con Plutus no hay un estado global o una “Máquina Virtual Cardano” a la que todos los contratos inteligentes Plutus puedan estar conectados. Con Ethereum como mencionamos, muchos agentes diferentes pueden acceder a un contrato inteligente basado en Ethereum debido al estado global compartido, pero con el modelo UTXO de Cardano ese no es el caso. Con Cardano, los contratos en sí mismos son componentes del UTXO y esencialmente actúan como condiciones que gobiernan cómo se utilizará el UTXO.
Los desarrolladores se encuentran actualmente con un desafío, ya que con solo un agente que puede consumir el UTxO, y por lo tanto, un contrato a la vez, lo que crea el llamado problema de “Concurrencia”. Si ponemos esto en el contexto de un DEX se hace más complejo por la cantidad de transacciones de pares de monedas (swap).
El modelo UTxO es determinista
El determinismo significa que un usuario puede predecir localmente (off-chain) cómo su transacción afectará al estado on-chain de la blockchain. En el contexto del procesamiento de transacciones y scripts, es un sinónimo de previsibilidad. Así se evitan resultados o fallos inesperados de validación de scripts, comisiones inesperadas y actualizaciones inesperadas del estado de la blockchain o del script.
En las eras de Shelley, Allegra y Mary, el proceso de validación de transacciones se realizaba en un solo paso. Alonzo añade las secuencias de comandos de Plutus, presentando un enfoque de validación en dos fases. El resultado de esta estrategia es predecible a la hora de realizar transacciones en el libro mayor y también garantiza una compensación justa a los nodos por su trabajo y uso de recursos.
Se realiza una pequeña cantidad de trabajo no compensado por parte de un nodo para determinar que una transacción no es procesable, pero sin que se realice la costosa validación de la segunda fase. Si la transacción es procesable, el nodo realiza la validación de la segunda fase de la transacción. En ambos casos, el nodo será compensado posteriormente por ambas fases de validación a través de la tarifa o la garantía recaudada de esta transacción. Esta garantía es la cantidad de ADA que se cobrará como tarifa en caso que falle la validación de un script en la fase 2.
Las críticas
Los críticos sostienen que las ventajas de eUTxO se exageran y los inconvenientes se subestiman, tildando de estrategia central de marketing de IOHK para Cardano.
Argumentan que el mayor inconveniente de eUTxO es que es imposible componer automáticamente las entradas que comparten el mismo estado, sin la necesidad de un coordinador. Sin ese coordinador, esto significa que en ciertos casos de uso, un eUTXO sólo puede ser gastado una vez por bloque.
Esto significa que para un grupo de usuarios de una determinada DApp, sólo 1 de ellos puede realizar una transacción cada 20 segundos, (lo que demora cada nuevo bloque en iniciarse), porque no pueden generarse varios UTxOs en la plataforma, para el mismo bloque. La única solución disponible actualmente, dicen, es un relé centralizado.
El mayor problema, critican, se presenta en DEX, ya que existen gran cantidad de UTxOs por la cantidad de transacciones. El intercambio descentralizado es una de las más importantes funciones en DeFi.
Cada vez que se comparte un estado común, necesita ser modificado (y registrado) en un bloque, y así se necesita un sistema de matcher/batcher fuera de la cadena. Esto se precisa con múltiples transacciones que quieren negociar el mismo Liquidity Pool (LP) en un intercambio.
Significa que, o bien sólo es posible una transacción por LP cada 20 segundos, lo cual no es viable por su lentitud, o bien las transacciones tienen que ser agrupadas en el mismo bloque con otras.
Esto último sólo se puede hacer mediante el uso de un repetidor centralizado: las transacciones se agrupan y se emparejan en un servidor centralizado, y luego se ejecutan como una sola transacción en la cadena L1.
Citan como ejemplo, el servidor centralizado de Ergolabs, que compara con el libro de órdenes y luego envía una transacción en su nombre a la cadena Cardano.
En una DEX descentralizada la billetera puede publicar una llamada de contrato directa en mainnet sin necesitar nada más que un cliente estándar de cadena principal descentralizada, pero sostienen que en Cardano, no.
En las cadenas que no son eUTxO, una transacción DEX es una transacción válida en mainnet, lo que significa que puede, simplemente, ser publicada. No se requieren servidores o código de backend.
La componibilidad DeFi ajustada no funcionará con UTxOs, porque los recursos compartidos como AMMs no pueden ser llamados en la cadena. Requieren un backend vivo para intermediar y gestionar todos los UTxOs. Un gran problema para las Apps que necesitan interactuar dentro de un ecosistema DeFi.
Las explicaciones de IOHK
IOHK explicó en un tweet explicó que Cardano es una blockchain UTxO (Unspent Transaction Output), que utiliza un paradigma de programación diferente para DApps que las blockchains basadas en account-balance como Ethereum.
El modelo específico que utiliza Cardano es el eUTxO (o modelo UTxO extendido) que ofrece una mayor seguridad, permite la previsibilidad de las tasas (sin sorpresas desagradables…) y ofrece una paralelización más potente
Aclaran que las DApps no están limitadas a 1 transacción por bloque. Si se diseña la aplicación con múltiples UTxO se puede imponer más paralelismo. Esto es inherente y es una de las ventajas del diseño de eUTxO tal y como está implementado en Plutus.
Contaron que pronto publicarán más documentación técnica para ayudar a los desarrolladores. El evento Alonzo HFC introducirá los bloques centrales de Plutus 1.0, en el inicio del crecimiento del ecosistema.
Cientos de desarrolladores han completado el curso Plutus Pioneers y decenas de proyectos ya han comenzado a desarrollarse en Plutus y se encuentran en diferentes etapas de experiencia y preparación. Se puede esperar una explosión de actividad en los próximos meses, a medida que la comunidad de desarrolladores crece en habilidades y conocimientos prácticos. Mientras tanto, la disponibilidad de herramientas y marcos se acelerará, empezando por el Plutus Application Backend (PAB). Otras herramientas y API de la comunidad estarán disponibles rápidamente.
Con el tiempo, los puentes y las cadenas laterales y otras soluciones de capa 2 harán que los desarrolladores se sientan más cómodos desarrollando para el modelo de account-balance, más conocido por el ambiente de blockchain.
Finalizaron el tweet diciendo que los próximos meses van a ser el periodo más emocionante de la historia de Cardano, con una enorme actividad dentro de la comunidad y el lanzamiento de una gran cantidad de nuevos proyectos y que lamentablemente, prevén muchos más ataques y FUD con intentos concertados de difundir información errónea.
IOHK presenta un documento que trata de Cómo escribir una aplicación Plutus escalable
Por último, publicó en su blog un artículo titulado: Concurrency and all that: Cardano smart contracts and the eUTXO model donde explica que el enfoque de Cardano para la implementación de DApp es diferente y, por lo tanto, requiere una curva de aprendizaje y un enfoque diferente. Esto es como trabajar con diferentes lenguajes de programación con el objetivo de implementar una solución, y cada lenguaje debe respetar su gramática.
Maximizar la concurrencia es una habilidad que debe aprenderse: los desarrolladores deben escribir código de una manera que restrinja severamente las oportunidades de contención (por ejemplo, evitando estados compartidos y dependencias accidentales). Luego, el sistema debe traducir esta concurrencia en paralelismo. Varios desarrolladores ya han identificado formas de abordar esto, mientras que otros aún están desarrollando soluciones.
De cualquier manera, es importante comprender que para implementar una DApp escalable en Cardano, un desarrollador no puede simplemente usar un contrato Ethereum adaptado. Cardano se basa en el modelo UTxO; no se basa en cuentas. Y esto significa que un solo estado en cadena no cumplirá con la propiedad de concurrencia en Cardano. En cambio, las DApps deberían dividir su estado en cadena en muchas UTXO. Esto aumentará la concurrencia en su aplicación, lo que permitirá un mayor rendimiento.
El equipo de educación ha compartido previamente una implementación simple de DEX estilo AMM en el curso Plutus Pioneer. Si bien esto es útil para fines de enseñanza, esta arquitectura no admitiría directamente un DEX comercial donde se requiere un enfoque de libro de pedidos y concurrencia adicional. Un desarrollador que busque implementar en la red principal de Cardano necesitaría mejorar la escalabilidad de la arquitectura en consecuencia.
Las propuestas en el ecosistema Cardano
Varios equipos de desarrollo, en forma individual, presentaron distintos abordajes para tratar la concurrencia en el modelo eUTxO.
Minswap ha conocido el desafío de la concurrencia desde que empezaron a construir en Cardano hace más de 6 meses. No es un defecto fundamental, sino simplemente un reto de diseño que debe ser abordado.
Minswap tiene varios enfoques para abordar este problema y está sopesando las ventajas y desventajas de cada solución. Los enfoques en la cadena que hemos explorado están limitados por el límite de memoria de las transacciones y los que están fuera de la cadena necesitan una entidad centralizada o un sistema L2 robusto. Ambos llevan tiempo y requieren una DEX simple y robusta primero.
Sundaeswap publicó en su blog un análisis. Tres palabras que puede ver entrar mucho en la discusión son “concurrencia”, “paralelismo” y “contención”. La concurrencia es la capacidad de varios actores para progresar en una tarea, sin interferir entre sí. El paralelismo es la capacidad de varios actores para avanzar en una tarea al mismo tiempo , sin interferir entre sí. La contención es cuando varios actores realmente interfieren entre sí.
Antes de hablar sobre soluciones, vale la pena abordar 3 conceptos erróneos:
- Concepto erróneo 1: Cardano tiene fallas porque solo permite 1 transacción por bloque. De hecho, es todo lo contrario. Cardano permite cientos de transacciones por bloque. En cambio, es correcto decir que Cardano permite que la salida de una transacción determinada se gaste una sola vez, mediante una sola transacción, por lo que los protocolos que brindan acceso a varias personas a la misma UTXO podrían enfrentar problemas de contención.
- Concepto erróneo 2: solo un usuario puede interactuar con un contrato inteligente por bloque / transacción. Tampoco es cierto; el punto de discusión está en torno al UTXO, pero muchos UTXOs pueden regirse por el mismo contrato inteligente. Esto se reduce fundamentalmente al cambio en la forma de pensar de Ethereum, donde llama a un contrato inteligente para que haga algo , y Cardano, donde bloquea las salidas con un contrato, que determina cuándo se pueden gastar más adelante.
- Concepto erróneo 3: la única forma de resolver esto es a través de la centralización. La centralización es una forma de resolver este problema, pero no es la única.
Para Sundaeswap parece haber dos categorías de soluciones: diseñar el protocolo para tolerar la segmentación de su estado o agregar interacciones con ese estado.
Se podría diseñar un DEX de modo que no requiriera un solo pool de liquidez. En cambio, la liquidez se fractura entre varios grupos, y cuanto más se fractura, más puertos hay para que las personas interactúen y menos contención sobre esos fondos. Sin embargo, cuanto más se fracturen los pools, menor será la eficiencia de capital que tendrá y mayor será el valor perdido en el arbitraje de pools cruzados. La parte inteligente, entonces, está en diseñar soluciones a esos problemas: liquidez concentrada estilo Uniswap v3, por ejemplo.
Alternativamente, un modelo de libro de pedidos para un intercambio, que en Ethereum es desastrosamente caro de mantener y actualizar, parece más adecuado para Cardano, donde cada pedido es un UTXO separado. La parte complicada, sin embargo, es que todavía tiene disputas sobre los pedidos más cercanos al precio actual. Una solución viable sería tener las órdenes de mercado listadas en cadena, y un agregador externo empareja y ejecuta estas órdenes. La parte inteligente, entonces, es asegurarse de que el agregador no tenga demasiado poder sobre el mercado.
Finalmente, podría crear un intercambio híbrido, donde la custodia de los fondos se descentraliza y se almacena en la cadena de bloques, pero la creación de mercado y la coincidencia se envían a través de un servidor backend central. Esto resuelve el problema de ingeniería, pero probablemente lo convierte en un corredor de bolsa fuertemente regulado, lo que conlleva sus propios desafíos.
La solución para SundaeSwap es diferente de las anteriores. Nos cuentan que están reservando su diseño y que muy pronto revelarán cómo funciona.
El equipo de desarrolladores de MELD, resume en un artículo algunas ideas para abordar la temática.
- División de UTxOs. Si solo se puede consumir un estado de UTxO por bloque, se puede dividir en UTxO más pequeños para gastarlos al mismo tiempo. Por ejemplo, tener varios pools de préstamos para que los prestamistas y prestatarios interactúen por bloque. Sin embargo, esta solución no suele ser eficiente en términos de capital. Es posible que un pool de préstamos no tenga suficientes activos para que un gran prestatario pueda pedir prestado. Cuando los prestamistas quieren retirar sus activos suministrados, tienen que consumir todas las UTxO del pool de préstamos a las que han prestado. Ambos casos requieren consumir múltiples UTxO para procesar una solicitud, lo que requiere más UTXO para evitar la congestión, lo que nuevamente reduce la cantidad de activos en cada grupo. Esto no parece un equilibrio fácil de resolver. Este diseño también solo funciona para aplicaciones sin estado compartido entre los subestados. Es difícil adaptar aplicaciones que sí lo hagan y aquellas que requieran sincronización o acumulación de sub-estados. En ciertas aplicaciones, como el consumo de precios de Oracle, puede ser plausible tener múltiples UTxO de solo datum similares.
- Procesamiento por lotes. La arquitectura de MELD pertenece a este grupo de soluciones. Las principales ventajas que han identificado en este momento son, Regla de validación determinista en cadena, donde los agentes fuera de la cadena solo pueden enviar la única salida correcta. Esto significa que no hay influencia alguna de ningún agente fuera de la cadena. Seguridad. Sin explotación de bordes por parte de agentes fuera de la cadena. Eficiencia de capital, ya que no se tiene que pagar más para que los agentes fuera de la cadena actúen con buenas intenciones. Sencillez, donde la arquitectura tiene un buen alcance. La infraestructura fuera de la cadena es mínima. No se tienen que diseñar funciones complejas de incentivos que puedan verse afectadas por las condiciones del mercado y que requieran una mayor gobernanza para ajustarse correctamente.
- Actualización diferida. La idea es reservar para crear UTxO de actualización como los pasos por lotes en esta arquitectura. Sin embargo, en lugar de aplicar constantemente las actualizaciones en un estado, se espera hasta que se requiera dicho estado en la cadena. Por ejemplo, en un proceso de votación de gobernanza, solo necesitamos consumir los votos cuando consumimos su propuesta para decidir si se aprueba o no. La aplicación constante de votos al estado de la propuesta corre el riesgo de congestión y tarifas de transacción innecesarias. El mundo fuera de la cadena no se ve afectado, ya que aún puede encontrar las UTxO de votación y mostrar a los usuarios el estado de la propuesta.
Los desarrolladores de ErgoDEX también plantearon el tratamiento que le darán a la concurrencia y los eUTxOs. En una entrevista en el canal de YouTube Cardano With Paul contaron que trabajarán en una solución de código off-chain con los SPOs, particularmente con los pequeños pools para alentar a la descentralización. El protocolo correrá un bot off-chain para elegir el SPO validador. Una tarifa de ejecución será agregada a la tarifa de transacción en la plataforma de ErgoDEX antes que la orden sea suscripta. Luego, cada bloque validado con múltiples transacciones, será movido al ledger y el pool que ejecute el bot ganador será recompensado con la tarifa de ejecución.
El equipo de Maladex escribió un tweet donde explican que en Ethereum todo es absolutamente secuencial, el pool selecciona las transacciones basándose en la maximización de la recompensa, luego todo se aplica al estado anterior uno por uno. Es muy fácil escribir en algo que es absolutamente secuencial y tiene memoria global, eso es lo que todo el mundo hace cuando escribe su primer programa, y algunos desarrolladores nunca se ocupan de la concurrencia. Cardano realmente tiene concurrencia, pero depende de los desarrolladores diseñar un sistema de concurrencia sólido con una buena experiencia de usuario.
En Maladex, dicen nunca pensaron que hubiera un problema de concurrencia, pero ahora con todo este FUD, quieren arrojar algo de luz al respecto. Lo único que es real, sí ahora están estableciendo un montón de patrones de diseño que en un par de años será norma para que todo el mundo lo use.
No es diferente al hecho de que DeFi haya tardado años en echar raíces en Ethereum, mientras que a AAVE le costó más de dos años aparecer y luego a UniSwap.
Mutual Knowledge Systems propone una solución interoperable con la blockchain Nervos: AVOUM for Nervos: Account-View-on-UTXO-Model.
La solución permitirá el despliegue seguro de los contratos “abiertos” en el blockchain Nervos, que no es posible actualmente, y traerá sus capacidades de contratos inteligentes en paridad con Ethereum.
Los usuarios pueden interactuar con las DApps utilizando el cómodo modelo account-balance, popularizado por Ethereum, pero sobre una Blockchain con capacidad de contrato inteligente que utiliza el modelo UTxO, más robusto pero más rígido, como Nervos, Cardano, Bitcoin Cash.
Los dos problemas principales que se resuelven son:
- Los contratos “abiertos” con un número ilimitado de participantes o transacciones pueden ser objeto de ataques DoS económicos por los que atacantes sofisticados pueden modificar el UTxO del contrato más rápido de lo que las víctimas pueden reaccionar, bloqueando así su interacción con él. Al hacer estas transacciones convenientemente maleables, los intermediarios (en equilibrio, los validadores) pueden competir para conseguir que las transacciones sean aceptadas por la blockchain a cambio de una comisión.
- Escribir scripts de desbloqueo de UTxO, en los que las transacciones sean convenientemente maleables, permite a los usuarios interactuar con los contratos como si la blockchain utiliza un modelo de account-balance; pero aplicar el patrón de diseño a mano requiere una gran disciplina y el resultado puede o no ser reconocido por los intermediarios de contabilización de transacciones (mineros). La solución consiste en automatizar esta disciplina utilizando una biblioteca Nervos adecuada.
Palabras finales
El diseño de Cardano fue concebido desde su origen con diseño de dos capas independientes para gestionar mejor la escalabilidad en el procesamiento de sus transacciones. La Cardano Settlement Layer (CSL) donde vive el libro contable (ledger) con sus saldos y la Cardano Computation Layer (CCL) donde se ejecuta todo el cómputo, es decir, donde tiene lugar toda la ejecución de los Contratos Inteligentes.
También fue concebido para ejecutar contratos inteligentes, y con un modelo contable diferente del que el propio Charles Hoskinson conocía como co-fundador de Ethereum.
Luego de más de 5 años de diseño de Cardano, por parte del equipo de desarrolladores de IOHK, con 116 research papers a la fecha, y análisis académicos con pares, cuando parte de la industria cripto criticó por su lento avance al desarrollo de Cardano, ¿no sería un error demasiado grosero haber omitido el asunto de la concurrencia?, un tema que es básico para la operación de los contratos inteligentes.
Más allá de las cuestiones técnicas, que son importantes, siempre es útil emplear el sentido común, que parece ser el menos común de los sentidos en la industria cripto.