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.
80 lines
3.7 KiB
Markdown
80 lines
3.7 KiB
Markdown
# Pruebas
|
||
|
||
Dos familias. Las de **criptografía** (test1–test4) verifican la derivación
|
||
watch-only —BIP32, secp256k1, RIPEMD-160, bech32— contra los **vectores
|
||
oficiales de los estándares**, no contra resultados propios. Las de
|
||
**heurísticas** (test5–test6) comprueban el analizador de privacidad contra
|
||
transacciones donde la respuesta se conoce de antemano.
|
||
|
||
Si un cambio rompe algo, estas pruebas lo dicen.
|
||
|
||
## Cómo ejecutarlas
|
||
|
||
Las de heurísticas se ejecutan directamente — se extraen solas del
|
||
`dashboard.html`, así que no se desactualizan:
|
||
|
||
```bash
|
||
node tests/test5.js
|
||
node tests/test6.js
|
||
```
|
||
|
||
Las de criptografía necesitan una preparación manual (pendiente de
|
||
automatizar igual que las otras dos):
|
||
|
||
Extraer el bloque criptográfico de `dashboard.html` a `crypto.js` (las líneas
|
||
que van desde `const B32 = {` hasta el final de `deriveAddresses`), añadir al
|
||
principio `const { webcrypto } = require("crypto"); const crypto = webcrypto;`
|
||
y al final la exportación:
|
||
|
||
module.exports = { B32, SECP, deriveChildPubkey, ripemd160, hash160, toBech32, deriveAddresses };
|
||
|
||
Después:
|
||
|
||
node test1.js # RIPEMD-160 y aritmética de curva
|
||
node test2.js # BIP32 y bech32 contra vectores oficiales
|
||
node test3.js # búsqueda de casos borde (diagnóstico)
|
||
node test4.js # regresión de los fallos ya corregidos
|
||
|
||
## Qué cubren
|
||
|
||
- **test1** — RIPEMD-160 con los seis vectores del estándar (incluido el de un
|
||
millón de caracteres), generador de secp256k1, múltiplos conocidos, y que
|
||
comprimir y descomprimir un punto sea reversible.
|
||
- **test2** — BIP32: clave pública y chain code de la raíz, y derivación no
|
||
endurecida `m/0`, contra los vectores 1 y 2 del propio BIP32. bech32: la
|
||
dirección P2WPKH del generador, en mainnet y testnet (BIP173).
|
||
- **test3** — sondeo de casos borde. Fue el que encontró los cuatro fallos de
|
||
validación corregidos el 2026-07-27.
|
||
- **test4** — comprueba que esos cuatro siguen cerrados: checksum rota, xpub
|
||
truncado, índice endurecido, índice negativo. Y que un `tpub` genera
|
||
direcciones de testnet, no de mainnet.
|
||
- **test5** — detección del output de cambio. Transacciones donde se sabe de
|
||
antemano cuál es el pago y cuál el cambio, más los niveles de "redondez" de
|
||
una cifra. Nació de dos fallos de la v1.15.0: una señal que se contaba dos
|
||
veces y un índice que podía señalar el pago como si fuera el cambio.
|
||
- **test6** — el analizador completo. Coherencia de la nota (que ninguna
|
||
transacción pueda puntuar negativo antes del clamp), los dos checks nuevos
|
||
—polvo gastado junto a otras monedas y consolidación pura— y que la guardia
|
||
de CoinJoin desactive las heurísticas que no aplican dentro de una mezcla.
|
||
|
||
Las cuatro primeras prueban criptografía; las dos últimas, heurísticas. Se
|
||
ejecutan igual: `node tests/testN.js`.
|
||
|
||
## Lo que estas pruebas NO cubren
|
||
|
||
Las heurísticas (test5, test6) se comprueban contra transacciones construidas
|
||
a mano, no contra la cadena real. Eso demuestra que la lógica hace lo que dice
|
||
—y ha bastado para encontrar fallos reales— pero no dice nada sobre cuántas
|
||
veces acierta ahí fuera. Medir eso exigiría un conjunto de transacciones reales
|
||
con la respuesta conocida de antemano, que es un trabajo distinto y pendiente.
|
||
|
||
La matemática es correcta, pero eso no es una auditoría. No cubren análisis
|
||
formal ni una revisión independiente: quien las escribió conoce la
|
||
implementación y comparte sus supuestos, que es justo el sesgo que rompe un
|
||
revisor externo. Siguen haciendo falta ojos de fuera antes de difundir el
|
||
proyecto ampliamente.
|
||
|
||
Tampoco aplican aquí los ataques de canal lateral: todo esto maneja **solo
|
||
claves públicas**. No hay secreto que filtrar; lo único que importa es que el
|
||
resultado sea correcto, y eso es lo que se comprueba.
|