
Quantum Cats es una colección de 3333 inscripciones ordinales que evolucionan con el tiempo para revelar diferentes obras de arte. Esta es la primera colección de inscripciones que evolucionará con el tiempo y se creará en una época de tarifas elevadas y un mercado de tarifas futuro impredecible. Este no es un artículo sobre las virtudes estéticas de las obras de arte (creo que lucen geniales) o razones para participar en el mercado de ellas; Este es un artículo sobre la implementación técnica de Quantum Cats. Creo que los desafíos de ingeniería que enfrentamos y las técnicas que implementamos para enfrentarlos son interesantes y potencialmente útiles tanto para los futuros creadores de Ordinals como para otros desarrolladores de aplicaciones de Bitcoin en general.
Antes de entrar en el meollo de la cuestión técnica de Quantum Cats, será útil comprender la experiencia que intentábamos crear. Los usuarios de Ordinals mantienen inscripciones (coleccionables digitales que se implementan en el protocolo de Ordinals y se transfieren con transacciones de Bitcoin) en billeteras de Bitcoin de autocustodia que tienen funciones de control de monedas y construcción de transacciones que permiten la transferencia de ordinales específicos, así como la firma de más tipos de transacciones complejas (como ofertas sin confianza e intercambios en mercados ordinales). Queríamos crear una colección de Inscripciones que evolucionara con el tiempo, agregando o cambiando atributos o rasgos de los Gatos.
La obra de arte de Inscripciones se publica en cadena en el testigo de una transacción Taproot (en una codificación especial llamada Sobre: el software con reconocimiento de ordinales analiza las transacciones buscando este sobre para encontrar inscripciones). Eso significa que cualquier dato de inscripción en particular es inmutable y no se puede cambiar una vez que se ha publicado (salvo una reorganización). Sin embargo, hay un par de maneras diferentes en las que podemos entregar el experiencia de cambiar la obra de arte, aunque la obra de arte en realidad nunca cambia (y de hecho, tener acceso a la obra de arte antigua es genial si te gusta más).
La recursividad es una característica de los ordinales donde una inscripción puede hacer referencia al contenido de otro. Por ejemplo, puede inscribir una página HTML y hacer que incluya imágenes que se encuentran en otras inscripciones. El software Ordinals representa páginas HTML en iframes, por lo que puede crear el contenido de un ordinal en el lado del cliente a partir de múltiples inscripciones. Las inscripciones HTML no pueden incluir contenido de la web en general, solo de otras inscripciones o de un pequeño conjunto de otros puntos finales proporcionados por el software de ordinales (por ejemplo, hay un punto final para recuperar la altura actual del bloque de bitcoin) . Esto significa que todas las inscripciones recursivas todavía están en la cadena, simplemente están descompuestas, lo que permite la componibilidad y la reutilización de componentes comunes. Por ejemplo, todos los Quantum Cats con un fondo rojo pueden hacer referencia a una única inscripción que contiene el fondo rojo, en lugar de que todos tengan que poner los mismos datos en la cadena.
Cuando una inscripción hace referencia a otra, lo hace por su ID de inscripción. Un ID de inscripción se compone del ID de la transacción Bitcoin en la que se revelan los datos de la inscripción, la letra iy luego un índice de salida de la inscripción que se crea. Por ejemplo, la inscripción 4b31771df21656d2a77e6fa18720a6dd94b04510b9065a7c67250d5c89ad2079i0 es la primera inscripción creada en la transacción bitcoin 4b31771df21656d2a77e6fa18720a6dd94b04510b9065a7c67250d5c89ad2079. Eso significa que si inscribe una imagen (como un png) y luego inscribe una página HTML que incluye el ID de inscripción de la imagen en una etiqueta img, puede hacer que la inscripción HTML represente el contenido de la inscripción de la imagen. Si la inscripción HTML se refiere a una inscripción de imagen que en realidad no está en la cadena (todavía), entonces el servidor de ordinales devolverá un error 404 (no encontrado), que la inscripción HTML puede tragar tranquilamente. Si firmamos previamente inscripciones de imágenes, pero no las transmitimos a la red Bitcoin, podemos obtener su ID de inscripción futura (porque son solo un ID de transacción y un índice) e incluir esos ID de inscripción en inscripciones HTML que hacer transmisión. Cuando alguien ve la inscripción HTML, puede representar el contenido de sus referencias que están en cadena, pero no podrá representar los componentes prefirmados pero no difundidos. A medida que se publiquen más componentes, la inscripción HTML podrá representarlos automáticamente. Este es el mecanismo central que utiliza la colección Quantum Cats para evolucionar su obra de arte: transacciones preestablecidas para rasgos que se revelan progresivamente con el tiempo. Como veremos, la gestión de tarifas y la dinámica del mercado introdujeron complejidades que hicieron que los Quantum Cats necesitaran algunas capas adicionales de indirección y características, pero las transacciones prefirmadas con ID de transacción precalculadas son la característica clave de Bitcoin que hizo posible la recolección.
Aunque el contenido de una inscripción prefirmada pero no revelada se desconoce antes de que se transmita la transacción, el mismo ID de inscripción tendrá el mismo contenido. Esto creó un problema: aunque las personas no pueden decir cuál sería un rasgo futuro (como un trasfondo o un rasgo corporal), podrían contar el número de veces que ocurrió una identificación de inscripción en particular y saber cuáles los rasgos futuros eran más o menos. raros y poder intercambiar gatos en sus evoluciones futuras. Realmente queríamos que las evoluciones fueran sorprendentes y divertidas, y no sabíamos de antemano qué efecto tendrían las evoluciones futuras con la relativa rareza de los diferentes gatos es muy divertida. Entonces, introdujimos una capa de indirección: cada gato se refiere a un «Conector de capa» prefirmado (pero no revelado) que asigna un gato mediante una identificación única a una obra de arte prefirmada. Eso significa, por ejemplo, que cada gato hace referencia al mismo conector de capa para su imagen de fondo inicial. Sólo una vez que este conector de capa se transmite a la red, las personas pueden saber qué orígenes son más o menos comunes. Esta técnica también permitió ahorrar espacio: dado que cada gato hace referencia a conectores de capa idénticos, el HTML para que el gato importe los conectores de capa se puede inscribir una vez y luego hacer referencia a cada una de las 3333 inscripciones de gato. De hecho, cada inscripción Cat se reduce a 109 bytes: solo un ID de gato único y una etiqueta de script para importar la lógica para buscar y renderizar el conjunto común de conectores de capa, buscar la obra de arte única para cada capa por gato. y renderizar. esa obra de arte. Poder mover el mapeo de cada Gato a su obra de arte desde las inscripciones de Gato individuales a una inscripción común, y agregar la capa de dirección indirecta preescrita no solo resolvió la filtración de información sobre la relativa rareza de los rasgos, sino que también ahorró ¡aproximadamente 5 BTC en costos de inscripción!
Con esta introducción de inscripciones de conector de capa y la factorización de la lógica de representación en un componente común, ahora se inscriben 4 tipos de activos:
- Obra de arte real para cada rasgo del Gato (una imagen de fondo, un cuerpo o los ojos)
- Un conector de capa que asigna un gato por su ID a un recurso artístico específico. Este mapeo ocurre una vez por “capa” (fondo, cuerpo, ojos, boca, etc.)
- La central lógica de despacho y renderizado. A esto lo llamamos el «Despachador». Es responsable de buscar un conector de capa, buscar la obra de arte del gato en el conector de capa, buscar ese recurso de obra de arte y luego representarlo en un lienzo en orden. Esta representación sucesiva en orden es la razón por la que modelamos la obra de arte como una capa.
- El Gato individual que se distribuye a un coleccionista. Tiene 109 bytes e incluye una identificación única y una referencia al despachador, que contiene todo el código de representación.
En Quantum Cats, hay varios cientos de recursos artísticos, 40 capas (es decir, 40 conectores de capas), 1 despachador y 3333 gatos. Las inscripciones Cat 3333 se refieren al ID de inscripción del Dispatcher, que se refiere a los ID de inscripción de los 40 conectores de capa, cada uno de los cuales se refiere a uno o más ID de inscripción de activos de obras de arte. Presignamos estos recursos en orden inverso: primero la obra de arte para obtener su ID de inscripción, luego los renderizamos en conectores de capa y los prefirmamos para obtener su ID de inscripción, luego renderizamos el Dispatcher y lo prefirmamos, y finalmente ensamblamos el Gato individual. . inscripciones.
Los ID de inscripción incluyen un ID de transacción de Bitcoin. Los ID de transacciones de Bitcoin son una función de sus entradas, salidas, versión y tiempo de bloqueo. Eso significa que si gastamos el UTXO que financia una transacción prefirmada en alguna otra transacción, nunca podremos volver a crear esa misma ID de transacción y romperemos nuestra referencia de inscripción prefirmada. Para evitar esto, creamos un UTXO para financiar cada transacción prefirmada y luego mantuvimos una base de datos para rastrear qué UTXO se asignó para financiar cada transacción prefirmada. También tuvimos controles de cordura automatizados para afirmar que no había dos inscripciones gastando el mismo UTXO, que cada transacción de confirmación de inscripción solo gastaba su UTXO asignado y que las entradas y salidas totales de todas las transacciones (incluidas las tarifas) eran las que esperábamos . Estos controles se ejecutaban cada vez que el sistema tocaba billeteras o llaves, y nos daban la confianza de que no se estaba firmando nada que no debería. Además, utilizamos billeteras segregadas para diferentes tipos de inscripción de activos, para agregar más protecciones contra un error que provoca la doble asignación de un UTXO. También construimos un arnés de prueba que revisó toda la prefirma y publicación de inscripciones en regtest y luego validó que los datos que terminaron en la cadena coincidían con los que había en nuestra base de datos del plano de control.
Prescribir transacciones de esta manera significaba que teníamos que comprometernos previamente con las tarifas que pagaría cada inscripción. No podemos saber cuáles serán las tarifas cuando finalmente revelemos estas evoluciones, así que lo que decidimos hacer es preferir las transacciones con una tarifa razonable y luego crear herramientas para aumentar las tarifas en el futuro si las fijamos demasiado bajas (si si prescribimos una tarifa más). alta de lo necesario, simplemente tendríamos que vivir con ella, por lo que parte del análisis aquí fue elegir una tarifa con la que nos sintiéramos cómodos incluso si resultaba que habíamos pagado de más). Además de utilizar un servicio de aceleración de transacciones (pagar a un minero fuera de banda para que incluya una transacción en un bloque incluso si paga tarifas inferiores a las del mercado), existen dos técnicas para aumentar la tasa de tarifa efectiva de una transacción: Reemplazar por-fee (RBF) y Child-Pay-For-Parent (CPFP). El RBF implica volver a gastar los insumos de una transacción en una nueva transacción que paga una tarifa más alta. Debido a que nuestra aplicación se basa en ID de transacciones confirmadas previamente, esta no era una opción. CPFP implica gastar el resultado no confirmado de una transacción en una nueva transacción que paga una tarifa más alta que la «matriz». Para que los mineros capturen las tarifas de esta transacción «secundaria», deben incluir tanto al padre como al hijo como un paquete. La tasa de tarifa efectiva termina siendo la tarifa total pagada dividida por el tamaño virtual total del paquete (todas las transacciones juntas). Dado que la transacción principal no se ve afectada, este era exactamente el mecanismo de aumento de tarifas que necesitábamos.
Un problema pendiente es que teníamos potencialmente cientos de transacciones a las que sería necesario aumentar las tarifas. Además de la dificultad de eliminar manualmente con precisión decenas o cientos de transacciones no confirmadas, también existen polít icas de retransmisión que impiden que un paquete de más de 101 KvB (kilobytes virtuales) o más de 25 transacciones se retransmita a través de la red. Eso significa que si necesitáramos 50 transacciones CPFP, querríamos hacerlas todas en paralelo, en lugar de en serie. Para lograr esto, creamos herramientas que:
- mire una lista de transacciones no confirmadas y para cada una calcule el costo para CPFP: aumente esas transacciones a una tasa de tarifa objetivo
- Agregue esas cantidades como resultados en una nueva transacción que gastó desde una única entrada hasta todos los UTXO necesarios para aumentar las transacciones de destino en paralelo.
- Solicitar al operador que envíe la cantidad total de bitcoins requerida (también calculó las tarifas para la transacción dividida) a una única dirección.
- Una vez recibido el depósito, transmitiría la transacción para dividir el depósito en un UTXO para cada transacción que debiera superarse.
- Luego construiría y transmitiría transacciones CPFP para cada una de las transacciones atascadas.
Probamos este sistema en Regtest con hasta 300 transacciones a la vez. ¡También tuvimos la oportunidad de usarlo cuando necesitábamos aumentar las tarifas de varias transacciones de revelación de conectores de capa en la red principal! Puede ver la transacción “dividida” aquí: https://mempool.space/tx/2ec4a8708524faf9901c69da8518b632ec31762730218d3b38ff40954cee882f Cada uno de esos resultados financieros al CPFP para aumentar una transacción de revelación de inscripción de 65 a 150 sat/vb.
Los activos artísticos representaron aproximadamente el 90% de los datos totales del proyecto. Lo que queríamos hacer era publicar de manera oportunista todo o la mayor parte del arte que podíamos cuando las tarifas eran bajas. Pero tampoco queríamos que la gente viera el arte antes de que los gatos estuvieran listos para evolucionar. Entonces, decidimos cifrar la obra de arte y luego publicar la clave de descifrado de la obra de arte con el conector de capa (que contiene el mapeo necesario para que un gato obtenga su rasgo). Esto nos permite desacoplar el paso de publicación de datos de la revelación del rasgo. Esto nos permitió aprovechar una época de tarifas más bajas para realizar la publicación masiva de datos y, al mismo tiempo, poder mostrar al mundo la obra de arte en un momento que tuviera sentido para la colección. La mecánica aquí es sencilla: antes de prefirmar los recursos de la obra de arte, toda la obra de arte para una capa en particular (nuevamente, piense en el fondo, los ojos o la boca) se cifra con una clave de cifrado por capa. . Esa obra de arte cifrada se utiliza en una inscripción prefirmada como un flujo de bytes. Luego, la clave de cifrado se representa en el conector de capa (que nuevamente está prefirmado). Cuando el despachador recupere un conector de capa, lee la asignación de Cat-ID -> recurso artístico y también la clave de descifrado para esa capa. Cuando recupera el recurso artístico, lo obtiene como una matriz de bytes y luego utiliza las bibliotecas de criptografía del navegador para descifrar la obra de arte como png y finalmente lo escribe en el lienzo.
En conjunto, cada Quantum Cat es una pequeña inscripción que recupera una inscripción común que contiene código de envío, descifrado y representación. Ese código recupera tantos conectores de capa como están disponibles en la cadena (algunos de ellos no lo estarán porque están prefirmados pero no se transmiten). Luego utiliza los ID de inscripción y las claves de descifrado en estos conectores de capa para recuperar ilustraciones cifradas en otras inscripciones, las descifra y luego las representa en un lienzo. Cuando necesitamos transmitir estas inscripciones prefirmadas, utilizamos transacciones CPFP paralelas masivas para aumentarlas hasta la tarifa correcta sin tener que comprometernos por adelantado con una tarifa demasiado alta. El resultado neto de todo esto es que los usuarios tienen un Quantum Cat en su billetera que evoluciona con nuevos rasgos y atributos con el tiempo, sin dejar de tener todos sus activos inmutables en Bitcoin.
Hay otros aspectos del proyecto que no hemos cubierto aquí: cómo el código del navegador gestiona los fallos intermitentes al recuperar todos estos activos, cómo se maneja la curación de una colección en evolución, cómo gestionamos el proceso de creación de UTXO para todos los activos prefirmados en en primer lugar (eso es fácil: es el mismo código de división UTXO descrito anteriormente para financiar los UTXO de CPFP). Pero espero que la discusión anterior le resulte interesante y útil, ya sea en un proyecto de inscripción u otro proyecto que involucre transacciones prefirmadas.
Esta es una publicación invitada de Rijndael. Las opiniones expresadas son enteramente propias y no reflejan necesariamente las de BTC Inc o Bitcoin Magazine.