diff --git a/CHANGELOG.md b/CHANGELOG.md index 98c56b2..c1688c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,15 @@ y el versionado sigue [Versionado Semántico](https://semver.org/lang/es/): `mixer` del conjunto de direcciones del actor y del union-find, y la atribución por huella salta esos nodos. - Verificado con el mismo caso: de 10 direcciones atribuidas a 0. +- **Tampoco atribuye al actor las direcciones de un custodio.** Misma raíz que + el fallo anterior, descubierta probando la poda por rama con un depósito real + en Bitfinex: el cluster CIOH ya excluía las direcciones de custodio, pero la + atribución por huella de software no, así que la hot wallet del exchange + acababa listada como "dirección del actor" mientras la conclusión, dos líneas + más abajo, la identificaba correctamente como Bitfinex. La dirección donde el + ladrón deposita es del exchange, no del ladrón. Ambos criterios están ahora + alineados: ni mezclas ni custodios entran por ninguna de las dos vías. + Verificado: de 2 direcciones atribuidas a 1 (solo la rama legítima). --- ## [1.10.1] — 2026-07-27 diff --git a/dashboard.html b/dashboard.html index e4d0ba3..a016483 100644 --- a/dashboard.html +++ b/dashboard.html @@ -4311,10 +4311,25 @@ // así que la huella sale "estable" por construcción, no porque sea el // mismo actor. Atribuir salidas de un CoinJoin por esa señal sería // señalar a terceros que solo coincidieron en la misma transacción. + // Dos exclusiones, por el mismo motivo de fondo: la huella de software + // solo dice algo del actor cuando la dirección PUEDE ser suya. + // - Mezclas: todos los participantes usan el mismo programa, así que la + // huella sale estable por construcción, no por ser el mismo actor. + // - Custodios: la dirección es del servicio, no de quien deposita. + // Atribuir una hot wallet de exchange "al actor" en un informe que + // puede acabar en una denuncia es señalar al mensajero. Además + // contradice la conclusión del propio informe, que la identifica como + // custodio. + // El cluster CIOH ya excluía los custodios (ver actorAddrSet); esto + // alinea la atribución por huella con ese mismo criterio. const fingerprintStableAddrs = new Set(); for (const n of allNodes) { if (n.stopReason === "mixer") continue; - if (n.fingerprintComparison?.changed === false) n.addresses.out.forEach(a=>fingerprintStableAddrs.add(a)); + if (n.fingerprintComparison?.changed === false) { + n.addresses.out.forEach(a => { + if (!(n.custodyAddrs || []).includes(a)) fingerprintStableAddrs.add(a); + }); + } } const attributed = [];