Artículo de Blog
Autor
Jonathan Jove
Fecha de publicación
Tarifas
Actualización de protocolo
A nadie le gusta pagar tarifas, pero las tarifas juegan un papel esencial en la salud de la red de Stellar al prevenir ataques de denegación de servicio. Pero solo porque las tarifas son importantes no significa que deban ser caras o inflexibles. En el Protocolo 11, introdujimos subastas de tarifas para mantener bajas las tarifas cuando la utilización de la red era baja. Ahora en el Protocolo 13, estamos introduciendo transacciones de aumento de tarifa para hacer flexibles las ofertas de tarifas.
¿Cómo cambias la tarifa en una transacción? En un sentido muy técnico, esta es una pregunta trampa. Es imposible cambiar la tarifa en una transacción. Lo que realmente puedes hacer es crear una nueva transacción con la tarifa deseada, luego recoger las firmas necesarias para formar un sobre de transacción. Podrías argumentar que esto es puramente una diferencia semántica. No lo es. Las dos transacciones requieren firmas diferentes, así que son de hecho diferentes. Si necesitas firmas de múltiples partes, entonces no hay garantía de que puedas convencer a todos para que realmente firmen la nueva transacción.
Quizás estés familiarizado con nuestra regla general para las tarifas, "elige la tarifa más alta que estés dispuesto a pagar para asegurar que tu transacción se incluya en el libro mayor." ¿Por qué querrías ajustar tu tarifa si sigues este consejo? No lo harías, por eso es un buen consejo. Pero esta estrategia ni siquiera tenía sentido antes del Protocolo 11 porque siempre pagabas la tarifa que especificabas. La única opción obvia para las personas que construyen transacciones pre-firmadas o pre-autorizadas era simplemente adivinar una tarifa que pareciera alta en ese momento, quizás 1 XLM. Unos años más tarde, cuando llega el momento de enviar una de esas transacciones, podrías descubrir que la tarifa mínima para ser incluido en el libro mayor es más alta de lo que anticipaste. Antes del Protocolo 13, estarías sin suerte.
No sabemos cuántas personas hicieron esto porque las transacciones pre-firmadas no se almacenan en el libro mayor. Pero sabemos que nos preocupa el problema, incluso si solo afectó a una transacción por un solo stroop de XLM. Los usuarios necesitan estar seguros de que será posible ejecutar sus transacciones, de lo contrario simplemente usarán otra red financiera para evitar el riesgo. Imagina que estabas comprando una casa y tu contrato requería que depositaras en garantía el 1% del precio de venta como un pago de seriedad. Entras en un contrato con un agente de garantía que autoriza al agente a desembolsar los fondos bajo ciertas circunstancias. Cuando llega el momento del desembolso, el agente te informa que el contrato es legalmente inaplicable y tus fondos han sido inaccesibles. Estás muy molesto y juras nunca usar ese agente de garantía nuevamente. Quizás incluso intentes tomar medidas legales contra el agente. Esta hipotética es análoga a no poder ejecutar una transacción pre-firmada, que es como un contrato aplicado por la red.
Antes de que pueda explicar qué es una transacción de aumento de tarifa, repasemos rápidamente algunos términos de Stellar. Una operación es la unidad más pequeña de trabajo en el protocolo de Stellar. Enviar un pago o gestionar una oferta son ejemplos de operaciones. Una transacción contiene hasta 100 operaciones que se aplican atómicamente, junto con otra información como la tarifa y el número de secuencia. Aunque a menudo hablamos de enviar una transacción a la red de Stellar, esto es un abuso sutil del lenguaje. En realidad, las transacciones no llevan firmas, por lo que no pueden ser enviadas a la red. Los sobres de transacción, que envuelven una transacción y las firmas correspondientes, son lo que los clientes realmente envían a la red.
En el Protocolo 13, hemos añadido no solo una transacción de aumento de tarifa sino también un sobre de transacción de aumento de tarifa. Como un sobre de transacción regular, un sobre de transacción de aumento de tarifa envuelve una transacción de aumento de tarifa y las firmas correspondientes. Pero una transacción de aumento de tarifa no contiene operaciones. ¡En su lugar, contiene un sobre de transacción! Una transacción de aumento de tarifa también especifica una tarifa y una cuenta que pagará esa tarifa, ambas anulan lo que se especificó en la transacción contenida.
Supongamos que tienes un sobre de transacción que no puede ser incluido en el libro mayor porque la tarifa es demasiado baja. La transacción requiere firmas de múltiples partes, y una de las partes se niega a firmar una nueva transacción con una tarifa más alta porque perderán dinero si la transacción se ejecuta. Las transacciones de aumento de tarifa te permiten evitar este conflicto por completo. Primero creas una transacción de aumento de tarifa que contiene el sobre de transacción que deseas enviar, especificando la tarifa que deseas pagar y la cuenta que la pagará. Si controlas esa cuenta, entonces puedes firmar la transacción de aumento de tarifa y formar un sobre de transacción de aumento de tarifa a partir de la transacción de aumento de tarifa y tu firma. Ahora esto puede ser enviado con éxito si la nueva tarifa es suficientemente alta.
¿Qué sucede cuando realmente envías un sobre de transacción a un nodo de Stellar-Core? Primero, valida el sobre de transacción. El proceso de validación puede considerarse como Stellar-Core comprobando que no hay razón obvia por la que el sobre de transacción no pueda ejecutarse con éxito. Esto incluye verificar que las firmas son válidas, que la tarifa por operación excede la tarifa base, y que el número de secuencia es secuencial. Las transacciones inválidas se descartan inmediatamente, mientras que las transacciones válidas se almacenan en la cola de transacciones. La cola de transacciones, que a veces se llama un pool de memoria o mempool en otros sistemas, es esencialmente el conjunto de sobres de transacción que el nodo consideraría para inclusión en el próximo libro mayor si ese nodo pudiera elegir unilateralmente.
Los sobres de transacción de aumento de tarifa pasan por un proceso similar. Pero a diferencia de los sobres de transacción, los sobres de transacción de aumento de tarifa admiten el mecanismo de reemplazo por tarifa. Cuando ocurre el reemplazo por tarifa, un sobre de transacción o sobre de transacción de aumento de tarifa en la cola de transacciones es reemplazado por un sobre de transacción de aumento de tarifa con el mismo número de secuencia y cuenta de origen, pero una tarifa que es al menos 10 veces más alta. Imagina, por ejemplo, que envías un sobre de transacción a un nodo de Stellar-Core que es aceptado porque su tarifa estaba por encima de la tarifa mínima. Pero tu sobre de transacción no se incluye en el libro mayor debido a la tarificación por congestión, y quieres acelerar el proceso. Sin el mecanismo de reemplazo por tarifa, no podrías enviar con éxito un sobre de transacción de aumento de tarifa con una tarifa más alta porque el número de secuencia no sería secuencial. Con él, sin embargo, realmente puedes aumentar la tarifa.
¿Por qué no puede ocurrir el reemplazo por tarifa para cualquier tarifa que sea más alta que la tarifa antigua? Definitivamente, esto habría sido más simple y menos costoso de usar. Pero también habría creado la posibilidad de un ataque de denegación de servicio. Tomamos la seguridad del sistema en serio, por lo que tuvimos que diseñar un mecanismo que mitigara este ataque.
La Propuesta de Avance del Núcleo Original (CAP) para las transacciones de aumento de tarifa fue escrita por OrbitLens de stellar.expert. Esta propuesta contenía una solución innovadora: el nodo de Stellar-Core simplemente debería agregar la transacción de aumento de tarifa a la cola de transacciones sin descartar la transacción original. Al elegir transacciones para incluir en el próximo libro mayor, un nodo incluiría una transacción más cero o más transacciones de aumento de tarifa que la contienen. Esto mitigó el potencial ataque de denegación de servicio, pero también fue una gran desviación del protocolo de Stellar existente. A veces el cambio fundamental está justificado, incluso requerido. La propuesta de OrbitLens fue aceptada por el comité de protocolo el 26 de junio de 2019 y comencé a trabajar en la implementación poco después con el objetivo de incluir transacciones de aumento de tarifa en el Protocolo 12. Cuando terminé mi primer borrador de la implementación, no estábamos seguros de su corrección.
La implementación de Stellar-Core se mantiene a los más altos estándares, por lo que no tuvimos más opción que excluir las transacciones de aumento de tarifa del Protocolo 12 y volver al tablero de dibujo. Esta fue una oportunidad, no una derrota. Cuando iteramos en un CAP, tratamos de identificar propiedades y garantías deseables, luego diseñamos un mecanismo que las logra. Nuestro principio rector es obtener las garantías más fuertes con el mecanismo más simple. La propuesta original proporcionó una garantía muy fuerte, porque habría sido posible enviar con éxito cualquier sobre de transacción de aumento de tarifa que aumente la tarifa de un sobre de transacción válido a cualquier tarifa que puedas pagar. El problema era que esta garantía solo se podía lograr con un mecanismo complejo.
Así que dirigimos nuestra atención a la búsqueda de un mecanismo más simple que aún pudiera proporcionar garantías relativamente fuertes. Descubrimos que requerir tarifas 10 veces más altas para activar el reemplazo por tarifa mitigaba el ataque de denegación de servicio. Aunque más débil que la garantía original, este enfoque aún garantiza que es posible aumentar la tarifa de cualquier sobre de transacción aunque no puedas elegir la tarifa exacta que deseas. Este enfoque se convirtió en la base para nuestra implementación actual.
Hay lecciones importantes aquí sobre cambiar el protocolo de Stellar. Primero, incluso los cambios que suenan simples, como hacer posible aumentar la tarifa en una transacción, pueden ser extremadamente desafiantes de diseñar e implementar. Segundo, necesitamos encontrar el equilibrio correcto entre proporcionar las garantías más fuertes que podamos y diseñar características que realmente puedan implementarse de manera segura.