Glosario / Direcciones y claves
Punto NUMS
- ¿Qué es el punto NUMS?
- El punto NUMS es una clave pública cuya clave privada no posee nadie, usada como clave interna de Taproot cuando la ruta de gasto cooperativa debe ser imposible.
Se especifica en el BIP-341.
Nothing Up My Sleeve (nada bajo la manga) es la propiedad: el punto sale de una receta pública y repetible, así que nadie puede afirmar que conoce su clave privada. BIP-341 publica uno de esos puntos, la coordenada x 0x50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0, obtenida calculando el hash de la codificación estándar sin comprimir del punto base G de secp256k1. Para una billetera, así es como una salida Taproot pasa a ser solo de script: gastable a través de su árbol de condiciones y de nada más.
Cómo funciona
Un punto NUMS empieza su vida como un hash, no como una clave.
Una clave pública corriente es el generador G multiplicado por un número secreto, y quien eligió ese número puede firmar. Un punto NUMS se construye al revés: se toma una cadena de caracteres pública e invariable, se calcula su hash y el hash de 32 bytes resultante se lee como una coordenada x. El ejemplo de BIP-341 calcula el hash de la codificación estándar sin comprimir del propio G, lo que no deja al autor ninguna libertad para amañar el valor de entrada. Convertir ese valor en un punto de la curva da una clave pública válida en todos los aspectos menos uno: firmar para ella exigiría resolver un logaritmo discreto, y BIP-341 cita 1 entre 2 elevado a 128 como el límite de seguridad del diseño.
Taproot aporta el resto. Una clave de salida de Taproot es la clave interna P desplazada a lo largo de la curva por un ajuste (tweak) que fija la raíz de Merkle del árbol de scripts: BIP-341 define t = hash_TapTweak(p || merkle_root) y después Q = P + int(t)G. Firmar para Q por la ruta de clave exige la clave privada que hay detrás de P, así que, cuando P es un punto NUMS, esa ruta queda cerrada y la ruta de script es la única vía de entrada. Un gasto así revela una hoja del árbol más un bloque de control de 33 + 32m bytes, donde m es el número de hash hermanos, que BIP-341 limita a 128.
Hay una filtración que conviene conocer. Un punto NUMS conocido se reconoce a simple vista, así que publicarlo tal cual en un bloque de control anuncia que la ruta de clave estaba muerta desde el principio. BIP-341 lo desaconseja: propone elegir un entero nuevo r, uniformemente al azar de 0 a n menos 1, y usar en su lugar H + rG, que no se distingue de una clave interna corriente. Si se conserva r, todavía se puede demostrar a un cofirmante que el punto era NUMS entregándoselo para que lo recalcule.
Dónde aparece
Un punto NUMS nunca aparece en una dirección, solo en el testigo de un gasto por ruta de script.
On-chain, la salida ocupa 34 bytes, OP_1 seguido de una inserción de datos de 32 bytes, igual que cualquier otra salida Taproot. La clave interna son los 32 bytes que siguen al primer byte del bloque de control, así que sale a la luz la primera vez que alguien gasta a través del árbol. Una salida que recibe fondos y nunca se gasta por la ruta de script nunca la revela.
Los descriptores hacen explícita la elección. BIP-386 exige que toda expresión de clave dentro de tr() sea x-only (solo coordenada x) y coloca la clave interna en primer lugar en tr(KEY, TREE), así que un punto NUMS en esa posición es la forma en que un descriptor declara que no existe ninguna ruta de clave. El caso simétrico es tr(KEY) sin árbol, donde BIP-386 cita el consejo de BIP-341 de que una salida sin ruta de script debería fijar de todos modos una ruta de script imposible de gastar.
Una clave interna NUMS hace que la recuperación dependa de la cadena de caracteres del descriptor y no solo de las frases semilla: las semillas reproducen las claves de las hojas, y nada en ellas registra el árbol ni el punto que está por encima. El flujo multisig de Sparrow le indica que conserve el descriptor, y esa instrucción pesa más aquí que en una billetera corriente de ruta de clave.
Punto NUMS frente a transacción de datos nulos
Un punto NUMS cierra una ruta de gasto, mientras que una transacción de datos nulos hace que una salida sea totalmente imposible de gastar. Una salida OP_RETURN está demostrablemente muerta por diseño: los nodos la eliminan del conjunto de UTXO y cualquier valor asignado a ella se quema. Las monedas que hay detrás de una clave interna NUMS no se queman: cada condición del árbol de scripts sigue gastándose con normalidad. La expresión que ambos comparten es "imposible de gastar", que abarca una salida entera en un caso y una sola rama en el otro.