fix: cuadrar el denominador de la nota y ampliar la redondez; dos checks nuevos
El denominador de la nota incluía dos pesos que nunca restan (rbf, peeling) y excluía uno que sí (input_linkage, hasta 30), así que las deducciones podían superarlo en 17 puntos y dar negativo. Corregido en ambas direcciones, con los cortes de banda recalibrados a 79/54 para que ninguna transacción cambie de banda por el arreglo. 'Redondo' equivalía a 'múltiplo de 0,001 BTC' por dos condiciones redundantes, y se le escapaban pagos de 10.000 o 50.000 sats. Ahora se mide por ceros finales y la señal se gradúa. Dos checks nuevos. El de polvo avisaba de una vinculación futura y nunca miraba si estaba ocurriendo delante: ahora la detecta cuando el polvo se gasta junto a monedas normales. Y la consolidación pura (N entradas, 1 salida) no disparaba el check de inputs innecesarios; ahora se nombra, sin cobrarla dos veces porque input_linkage ya la penaliza. tests/test6.js cubre lo nuevo y la coherencia de la nota.
This commit is contained in:
@@ -10,6 +10,64 @@ y el versionado sigue [Versionado Semántico](https://semver.org/lang/es/):
|
||||
- **MENOR** — características nuevas que no rompen lo anterior
|
||||
- **PARCHE** — arreglos de errores
|
||||
|
||||
---
|
||||
## [1.16.0] — 2026-08-08
|
||||
### Corregido
|
||||
- **El denominador de la nota de privacidad no cuadraba con los pesos.** La
|
||||
nota se calcula como `100 - (deducciones / maxPossible) * 100`, donde
|
||||
`maxPossible` es la suma del objeto `weights`. Ese objeto tenía dos
|
||||
desajustes, en direcciones opuestas y ninguno intencionado:
|
||||
- Incluía `rbf` (5) y `peeling` (8), que son informativos y **nunca restan**.
|
||||
Trece puntos de denominador imposibles de alcanzar, que inflaban
|
||||
sistemáticamente todas las notas.
|
||||
- **No** incluía `input_linkage`, que resta hasta 30 desde una variable
|
||||
suelta. Las deducciones podían superar al denominador en 17 puntos y dar
|
||||
una nota negativa, tapada solo por el `Math.max(0, …)`.
|
||||
- Ahora todo lo que puede restar está en `weights` y nada más lo está. Los
|
||||
cortes de banda pasan de 75/45 a 79/54, que son los valores que hacen que
|
||||
una transacción reciba **exactamente la misma banda que antes** con el
|
||||
denominador corregido. Queda anotado en el código que normalizar por la
|
||||
suma de los pesos obliga a recalibrar cada vez que se añade un check —
|
||||
porque cada check nuevo hace parecer menos graves a los anteriores.
|
||||
- El texto explicativo bajo la nota derivaba la banda por su cuenta con los
|
||||
cortes antiguos escritos a mano. Ahora usa la banda ya calculada.
|
||||
- **"Cifra redonda" estaba mal definido.** La condición era
|
||||
`v % 1000000 === 0 || v % 100000 === 0 || v % 10000000 === 0`, donde la
|
||||
primera y la tercera sobran: todo múltiplo de un millón lo es de cien mil.
|
||||
Equivalía a "múltiplo de 0,001 BTC", así que pagos tan redondos como 10.000
|
||||
o 50.000 sats —de lo más común con las comisiones de hoy— no se veían. La
|
||||
heurística estaba infrautilizada, no equivocada.
|
||||
- Ahora se mide por ceros finales y la señal se gradúa: pagar 0,5 BTC
|
||||
clavados delata más que pagar 0,0123, y la penalización lo refleja.
|
||||
- El didáctico dice ahora el punto ciego: si pagas una cantidad redonda **en
|
||||
euros**, en BTC sale un número con todos sus decimales y esta heurística no
|
||||
ve nada.
|
||||
|
||||
### Añadido
|
||||
- **Nuevo aviso: se gasta polvo junto a otras monedas.** El check de polvo
|
||||
advertía de que una salida diminuta "quedará vinculada con las demás si se
|
||||
gasta junto a ellas" — y la aplicación nunca miraba si eso estaba ocurriendo
|
||||
delante de ella, pese a tener el dato en la mano. Ahora lo mira: si entre las
|
||||
entradas hay una moneda de tamaño polvo gastada junto a otras de importe
|
||||
normal, el ataque ya no es una hipótesis, se acaba de consumar, y se dice con
|
||||
CERTEZA. No aplica en CoinJoin ni cuando solo se gasta polvo, que no revela
|
||||
vinculación nueva.
|
||||
- **La consolidación pura ya no pasa desapercibida.** Una transacción de N
|
||||
entradas a **una sola salida** —el acto que más privacidad destruye de una
|
||||
vez— no disparaba el check de inputs innecesarios: su condición exige que una
|
||||
entrada cubra el pago *y sobre*, y en una consolidación la salida vale casi
|
||||
lo mismo que la suma de entradas. Comprobado con 20 entradas a 1 salida.
|
||||
Ahora se nombra como lo que es, con certeza. No suma penalización propia a
|
||||
propósito: la vinculación ya la cobra `input_linkage`, y cobrarla dos veces
|
||||
sería repetir el error que este mismo repaso acaba de corregir.
|
||||
- `tests/test6.js` — el analizador completo contra transacciones construidas a
|
||||
mano: coherencia de la nota, los dos checks nuevos y la guardia de CoinJoin.
|
||||
- `tests/test5.js` gana la comprobación de los niveles de redondez.
|
||||
- `tests/README.md` explica ahora las dos familias de prueba y deja escrito que
|
||||
las heurísticas se comprueban contra transacciones fabricadas, no contra la
|
||||
cadena real: eso demuestra que la lógica hace lo que dice, pero no cuántas
|
||||
veces acierta ahí fuera.
|
||||
|
||||
---
|
||||
## [1.15.0] — 2026-08-08
|
||||
### Corregido
|
||||
|
||||
Reference in New Issue
Block a user