From f690e1783b07fbaf7ff7e88aca92fafbf4478295 Mon Sep 17 00:00:00 2001 From: Aitor Date: Thu, 4 Jun 2026 11:03:54 +0200 Subject: [PATCH] feat: check legacy P2PKH/P2SH; fixtures #2 #6 #7 #8 #9 #10 validados --- FIXTURES.md | 70 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 7 deletions(-) diff --git a/FIXTURES.md b/FIXTURES.md index 949f44a..916a44a 100644 --- a/FIXTURES.md +++ b/FIXTURES.md @@ -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: