Qué pasó
El 20 de agosto de 2026 Bitcoin Core integró el
pull request 35161. No cambia ningún
comportamiento. Añade un comentario de documentación a ComputeMerkleRoot, explica dentro
del bucle por qué una comprobación se ejecuta en todos los niveles del árbol, y añade un
test llamado merkle_test_mutated_return_value. La
cabecera ahora
enuncia el contrato: "Calcula una raíz de Merkle a partir de los hashes de hoja indicados.
Si no es nulo, *mutated se pone a verdadero si dos hashes idénticos quedan emparejados en
cualquier nivel del árbol antes del paso de duplicación por número impar, y a falso en caso
contrario". El comportamiento que describe viene del arreglo de CVE-2012-2459. Hasta este
mes vivía en un comentario de advertencia y en la memoria de quienes habían revisado el
código.
Qué cambia
La cabecera de un bloque se compromete con sus transacciones a través de una sola raíz de merkle de 32 bytes: se hacen hashes de los identificadores de transacción por pares, luego de esos resultados por pares, y así hasta que queda un único valor. La versión de Bitcoin tiene una particularidad sobre la que el propio archivo lleva años advirtiendo: cuando un nivel contiene un número impar de hashes, el último se duplica para que la cuenta quede par.
Esa particularidad hace que dos listas de transacciones distintas produzcan la misma raíz.
El comentario de
src/consensus/merkle.cpp
da el ejemplo: las listas [1,2,3,4,5,6] y [1,2,3,4,5,6,5,6] construyen la misma raíz
"(porque el hash tanto de (F) como de (F,F) es C)". Así que cualquiera puede tomar un bloque
válido, añadir copias de sus dos últimas transacciones y entregarle el resultado a un nodo.
Misma raíz de merkle, misma cabecera, misma prueba de trabajo. La
copia es claramente inválida, porque gasta dos veces las mismas entradas. El daño está en lo
que ocurre después: "Si el nodo receptor pasa entonces a marcar ese bloque como
permanentemente inválido, no aceptará versiones posteriores del mismo bloque sin modificar
(y por tanto potencialmente válidas)". Una copia falsificada dejaría a un
nodo fuera del bloque real, que lleva el mismo hash.
La defensa de Core es detectar la duplicación y tratarla "igual que si el bloque tuviera una
raíz de merkle inválida". El rechazo lleva su propio código, BLOCK_MUTATED, descrito en
consensus/validation.h
como "los datos del bloque no coincidían con los datos comprometidos por la prueba de
trabajo".
Lo que el pull request fija es la parte que una refactorización podría romper sin que nadie lo notara. Los dos hashes idénticos no tienen por qué ser hojas. En el ejemplo anterior coinciden un nivel más arriba, así que el bucle ahora indica: "Comprueba todos los niveles porque los pares iguales pueden aparecer por encima de las hojas, como en la construcción [1,2,3,4,5,6,5,6] descrita arriba". La otra mitad del contrato es que la raíz devuelta se calcula sobre la entrada completa, se haya encontrado un duplicado o no, de modo que quien llama a la función no puede leer la bandera levantada como permiso para ignorar el valor que la acompaña. El test nuevo sujeta ambas cosas.
Qué no cambia
No se movió ninguna regla de consenso. Ningún nodo valida nada de otra manera, y no hay nada que actualizar. La vulnerabilidad se arregló en 2012. Lo que ocurrió en agosto de 2026 es que su defensa consiguió una descripción y un test dirigido justo a ella.
Dejar una regla por escrito no vuelve seguro el código a la hora de cambiarlo. Hace que un cambio equivocado falle en voz alta. Este trabajo existe porque la pregunta surgió durante refactorizaciones anteriores y se resolvió en la revisión y no en el archivo, que es precisamente el estado que produce una regresión cuando otra persona lee el mismo bucle dos años después y ve una comparación redundante que parece merecer un borrado. El comentario ahora admite que seguir después del primer duplicado es "redundante", y dice por qué se queda igualmente: los bloques mutados no deberían propagarse, y el número de comparaciones es el mismo en cualquier caso.
La particularidad sigue intacta. Los niveles impares siguen duplicando el último hash, que es la razón por la que el archivo abre dirigiéndose a alguien que no es desarrollador de Bitcoin: "ADVERTENCIA: quien lea esto porque está aprendiendo sobre criptografía o diseñando un sistema nuevo que usará árboles de Merkle debe tener en cuenta que el siguiente algoritmo de árbol de Merkle tiene un fallo serio relacionado con los txid duplicados".
Contexto
CVE-2012-2459 pertenece a un pequeño conjunto de decisiones de diseño de Bitcoin que se reconocen como errores y no se pueden deshacer, porque la regla que los produce es la regla que ya siguen todos los nodos. Lo que sí se puede hacer es contenerlos, y después mantenerlos contenidos. La contención lleva catorce años aguantando. Este cambio va de la segunda parte, y el pull request es claro sobre lo que lo motivó: dos rondas previas de trabajo sobre la misma función, en las que el comportamiento hubo que reconstruirlo cada vez a partir de la discusión.
