feat: check legacy P2PKH/P2SH; fixtures #2 #6 #7 #8 #9 #10 validados

This commit is contained in:
Aitor
2026-06-04 11:03:54 +02:00
parent 2874f7c933
commit f690e1783b
+63 -7
View File
@@ -21,15 +21,15 @@ nodo y corrige la fila).
| # | Tipo | txid | Resultado esperado | Verificado |
|---|------|------|--------------------|------------|
| 1 | Whirlpool CoinJoin (5×5, 2019) | `323df21f0b0756f98336437aa3d2fb87e02b59f1946b714a7b09df04d429dec2` | CoinJoin detectado (✓ verde), banda ALTA, fingerprint "Samourai/Sparrow (Whirlpool)" | ✅ 2026-06-03 |
| 2 | WabiSabi CoinJoin | `fb596c9f675471019c60e984b569f9020dac3b2822b16396042b50c890b45e5e` | CoinJoin grande, banda ALTA, "Wasabi" inferido | |
| 3 | JoinMarket CoinJoin | `4f112abd2eefe3484a7bbf7c1731f784cba19de677468835145e9c448fb18b7d` | CoinJoin con outputs iguales, verificar mínimo ~10k sats | |
| 2 | WabiSabi CoinJoin | `fb596c9f675471019c60e984b569f9020dac3b2822b16396042b50c890b45e5e` | CoinJoin grande, banda ALTA, "Wasabi" inferido | ✅ 2026-06-04 |
| 3 | JoinMarket CoinJoin | `4f112abd2eefe3484a7bbf7c1731f784cba19de677468835145e9c448fb18b7d` | CoinJoin con outputs iguales, verificar mínimo ~10k sats | ⚠️ txid incorrecto — 2 inputs/4 outputs, no es JoinMarket inequívoco. Sustituir por txid real. |
| 4 | Batch payment 144 outputs (F2Pool, 2022-02-15) | `ef5d100a70eea9b7349a40fdfd51064fc5cebf5e3b4240f92591569836896949` | 1→144 outputs, **NO** CoinJoin, banda **MEDIA**, check "Pago por lotes" penaliza (45) | ✅ 2026-06-03 |
| 5 | Dusting de privacidad (555 sats, 2018) | `655c533bf059721cec9d3d70b3171a07997991a02fedfa1c9b593abc645e1cc5` | Salida de 555 sats detectada como "posible dusting" (POSIBLE), banda MEDIA, tono neutro | ✅ 2026-06-03 |
| 6 | Taproot + OP_RETURN | `0bf67b1f05326afbd613e11631a2b86466ac7e255499f6286e31b9d7d889cee7` | OP_RETURN detectado (presencia/tamaño), banda BAJA | |
| 7 | Legacy P2PKH simple | `0b6461de422c46a221db99608fcbe0326e4f2325ebf2a47c9faf660ed61ee6a4` | Tipo legacy, fingerprint conservador, banda MEDIA/BAJA | |
| 8 | Taproot script-path | `37777defed8717c581b4c0509329550e344bdc14ac38f71fc050096887e535c8` | Taproot reconocido | |
| 9 | Bare multisig | `60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1` | Multisig reconocido | |
| 10 | OP_RETURN con datos ASCII | `8bae12b5f4c088d940733dcd1455efc6a3a69cf9340e17a981286d3778615684` | OP_RETURN detectado (solo presencia/tamaño, **no** mostrar contenido) | |
| 6 | Taproot + OP_RETURN | `0bf67b1f05326afbd613e11631a2b86466ac7e255499f6286e31b9d7d889cee7` | OP_RETURN detectado (presencia/tamaño), banda BAJA | ✅ 2026-06-04 |
| 7 | Legacy P2PKH simple | `0b6461de422c46a221db99608fcbe0326e4f2325ebf2a47c9faf660ed61ee6a4` | Tipo legacy, fingerprint conservador, banda MEDIA/BAJA | ✅ 2026-06-04 |
| 8 | Taproot script-path | `37777defed8717c581b4c0509329550e344bdc14ac38f71fc050096887e535c8` | Taproot reconocido | ✅ 2026-06-04 |
| 9 | Bare multisig | `60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1` | Multisig reconocido | ✅ 2026-06-04 |
| 10 | OP_RETURN con datos ASCII | `8bae12b5f4c088d940733dcd1455efc6a3a69cf9340e17a981286d3778615684` | OP_RETURN detectado (solo presencia/tamaño, **no** mostrar contenido) | ✅ 2026-06-04 |
## Direcciones
@@ -144,6 +144,62 @@ pero no se copió bien al repo, y se presentó una versión sin el cambio. Lecci
verificar con grep que el archivo presentado contiene el cambio antes de
desplegar.
### 2026-06-04 — Fixture #2 (WabiSabi CoinJoin)
WabiSabi usa outputs de valor variable (a diferencia de Whirlpool con denominaciones fijas),
por lo que `isGenericCJ` no lo detectaba. Se encontraron y corrigieron cuatro fallos:
1. **CoinJoin no detectado**: el motor solo reconocía CoinJoin por outputs de igual valor.
Se añadió una tercera variante (`isStructuralCJ`): muchos inputs Y outputs (≥10 cada uno),
ratio inputs/outputs entre 0.5 y 2, y sin output dominante (< 30% del valor total).
WabiSabi, JoinMarket y mezclas similares con outputs variables ahora se detectan.
2. **Checks erróneos en rojo**: "Mezcla de tipos de script en inputs" e "Inputs innecesarios"
aparecían con ✗ rojo en una mezcla. En un CoinJoin ambas condiciones son esperadas
(participantes distintos aportan UTXOs de tipos y valores distintos). Ahora salen con
punto gris e `informativo` cuando `likelyCJ` es true, sin penalización.
3. **Fingerprinting en rojo**: "Fingerprinting de wallet" aparecía con ✗ rojo aunque
no penalizara. En un CoinJoin identificar el software es informativo, no un problema.
Ahora sale con punto gris cuando `likelyCJ` es true.
4. **Batch no suprimido**: el check de batch requería `!likelyCJ` para suprimirse, pero
como WabiSabi no se detectaba como CoinJoin, `likelyCJ` era false y el batch disparaba.
Resuelto al corregir la detección (punto 1).
### 2026-06-04 — Fixtures #7, #8, #9, #10
**#7 Legacy P2PKH (2016):** el motor no tenía check para tipo de script legacy.
Se añadió el check "Tipo de script legacy (P2PKH/P2SH)" (id: legacy_type, certeza
CERTEZA, peso 15, actionability: wallet). Detecta inputs con tipo `p2pkh` o `p2sh`
e informa que forman un conjunto de usuarios cada vez más pequeño. La banda queda
en ALTA para una tx legacy limpia — decisión deliberada: calibrar la alarma al
riesgo real, no exagerar. Un 15 informa sin alarmar.
**#8 Taproot script-path (2021):** sin cambios. Motor correcto — banda ALTA,
fingerprint "Sparrow" razonable (Taproot + RBF + BIP69). Fixture cerrado.
**#9 Bare multisig (2012):** sin cambios. No se añadió check específico de bare
multisig — caso marginal (formato obsoleto, prácticamente nadie lo usa) y el
problema real de privacidad (reutilización de direcciones 25) ya está cubierto.
Decisión: no añadir complejidad para un caso que no afecta al usuario tipo.
**#10 OP_RETURN ASCII ("charley loves heidi", 2014):** sin cambios necesarios.
El check de OP_RETURN añadido en el fixture #6 funciona correctamente — detecta
presencia y tamaño, banda BAJA, y no muestra el contenido ("charley loves heidi"
visible en mempool.space pero no en Txoko). Comportamiento correcto.
### 2026-06-04 — Fixture #6 (Taproot + OP_RETURN)
La tx tiene un output OP_RETURN confirmado (visible en mempool.space), pero el motor
no lo detectaba en el informe de privacidad. Se encontraron y corrigieron dos fallos:
1. **OP_RETURN no aparecía en el informe**: `isOpReturn` existía solo para filtrar
outputs gastables, pero nunca generaba un check. Se añadió el check "Datos OP_RETURN"
(id: op_return, certeza CERTEZA, peso 30, no corregible) con detalle de número de
outputs y bytes totales. No muestra el contenido — solo presencia y tamaño.
2. **Banda incorrecta (ALTA en lugar de BAJA)**: el peso 30 no era suficiente para
bajar la banda porque el denominador (`maxPossible`) absorbe la penalización. Se
añadió un cap explícito: cuando `hasOpReturn` es true, el score se limita a 44
(máximo de banda BAJA) independientemente del resto de señales.
Pendiente anotado (no bloqueante): el fingerprint dice "Wallet Taproot nativo" cuando
el input es Multisig 2 de 2 P2SH. El motor está leyendo el tipo del output de cambio
en lugar del input. Certeza POSIBLE — no afecta a la banda ni al análisis principal.
### 2026-06-03 — Fixture #A (dirección de Satoshi, reutilización extrema)
El motor clasificó bien la reutilización extrema (62.994 usos → reutilización
40, legacy 20, banda BAJA). Pero se encontraron dos fallos de cara al usuario: