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 | | # | Tipo | txid | Resultado esperado | Verificado |
|---|------|------|--------------------|------------| |---|------|------|--------------------|------------|
| 1 | Whirlpool CoinJoin (5×5, 2019) | `323df21f0b0756f98336437aa3d2fb87e02b59f1946b714a7b09df04d429dec2` | CoinJoin detectado (✓ verde), banda ALTA, fingerprint "Samourai/Sparrow (Whirlpool)" | ✅ 2026-06-03 | | 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 | | | 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 | | | 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 | | 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 | | 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 | | | 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 | | | 7 | Legacy P2PKH simple | `0b6461de422c46a221db99608fcbe0326e4f2325ebf2a47c9faf660ed61ee6a4` | Tipo legacy, fingerprint conservador, banda MEDIA/BAJA | ✅ 2026-06-04 |
| 8 | Taproot script-path | `37777defed8717c581b4c0509329550e344bdc14ac38f71fc050096887e535c8` | Taproot reconocido | | | 8 | Taproot script-path | `37777defed8717c581b4c0509329550e344bdc14ac38f71fc050096887e535c8` | Taproot reconocido | ✅ 2026-06-04 |
| 9 | Bare multisig | `60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1` | Multisig reconocido | | | 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) | | | 10 | OP_RETURN con datos ASCII | `8bae12b5f4c088d940733dcd1455efc6a3a69cf9340e17a981286d3778615684` | OP_RETURN detectado (solo presencia/tamaño, **no** mostrar contenido) | ✅ 2026-06-04 |
## Direcciones ## 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 verificar con grep que el archivo presentado contiene el cambio antes de
desplegar. 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) ### 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 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: 40, legacy 20, banda BAJA). Pero se encontraron dos fallos de cara al usuario: