feat: deteccion de dusting de privacidad (POSIBLE) ademas del dust tecnico; fix: tono neutro en dust

This commit is contained in:
Aitor
2026-06-03 20:03:14 +02:00
parent d8a35d94cf
commit 8d0c2620d3
2 changed files with 58 additions and 11 deletions
+37 -10
View File
@@ -1247,17 +1247,44 @@
return 546; // Legacy P2PKH / P2SH / desconocido
};
const dustOutputs = tx.vout.filter(v => v.value > 0 && v.value < dustThreshold(v.scriptpubkey_type));
const hasDust = dustOutputs.length > 0;
checks.push({
id:"dust", label:"Outputs de dust detectados", certainty:"CERTEZA", pass:!hasDust,
actionability: "no_corregible",
detail: hasDust
? `${dustOutputs.length} output(s) por debajo del umbral de dust (${dustOutputs.map(d=>d.value+"sat").join(", ")}). Hecho: hay salidas diminutas. Interpretación: podría ser un ataque de dusting, pero también un cambio diminuto de tu propio wallet o una salida de protocolo (Lightning, inscripciones). No se puede distinguir solo con esta transacción — por precaución, trátalo como dust y no lo gastes junto a otros UTXOs.`
: "Sin outputs de dust (según el umbral de cada tipo de salida).",
didactic: "Un ataque de dust envía cantidades mínimas a múltiples direcciones. Cuando el receptor gasta ese dust combinándolo con otros UTXOs, revela qué UTXOs pertenecen al mismo wallet. Es una técnica de surveillance — pero no toda salida diminuta es un ataque: también las hay legítimas (cambios pequeños, salidas de protocolo). Lo prudente es no gastar dust sin querer.",
penalty: weights.dust,
// Dusting de privacidad: salidas pequeñas pero por ENCIMA del umbral técnico
// (un atacante manda 555, 888... gastables a propósito para que no sean
// "dust técnico" y el receptor las tenga en el wallet). No es un hecho como
// el dust técnico, sino una sospecha -> certeza POSIBLE.
const DUSTING_CEIL = 1000;
const dustingOutputs = tx.vout.filter(v => {
const th = dustThreshold(v.scriptpubkey_type);
return v.value >= th && v.value < DUSTING_CEIL;
});
if (hasDust) deductions += weights.dust;
const hasDust = dustOutputs.length > 0;
const hasDusting = !hasDust && dustingOutputs.length > 0;
if (hasDust) {
checks.push({
id:"dust", label:"Outputs de dust detectados", certainty:"CERTEZA", pass:false,
actionability: "no_corregible",
detail: `${dustOutputs.length} output(s) por debajo del umbral de dust (${dustOutputs.map(d=>d.value+"sat").join(", ")}). Hecho: hay salidas por debajo del mínimo económico de la red. Interpretación: podría ser un ataque de dusting, pero también un cambio diminuto de tu propio wallet o una salida de protocolo (Lightning, inscripciones). No se puede distinguir solo con esta transacción. Consecuencia: si esa salida se gasta junto a otros UTXOs, queda vinculada con ellos — que es justo lo que persigue un ataque de dusting.`,
didactic: "Un ataque de dust envía cantidades mínimas a múltiples direcciones. Cuando el receptor gasta ese dust combinándolo con otros UTXOs, revela qué UTXOs pertenecen al mismo wallet. Es una técnica de surveillance — pero no toda salida diminuta es un ataque: también las hay legítimas (cambios pequeños, salidas de protocolo). La marca se materializa solo si el dust se gasta junto a otras monedas.",
penalty: weights.dust,
});
deductions += weights.dust;
} else if (hasDusting) {
checks.push({
id:"dust", label:"Salida muy pequeña (posible dusting)", certainty:"POSIBLE", pass:false,
actionability: "no_corregible",
detail: `${dustingOutputs.length} output(s) de cantidad muy pequeña (${dustingOutputs.map(d=>d.value+"sat").join(", ")}), por encima del mínimo técnico pero inusualmente bajos. Hecho: son salidas diminutas pero gastables. Interpretación: compatible con un dusting de privacidad (cantidades pequeñas enviadas a propósito por encima del umbral de dust para que el receptor las conserve), aunque también con un pago o cambio pequeño legítimo. No se puede confirmar solo con esta transacción. Consecuencia: si esa salida se gasta junto a otros UTXOs, queda vinculada con ellos.`,
didactic: "El umbral de dust técnico (≈546 sats) marca lo que la red considera antieconómico de gastar. Pero un dusting de privacidad suele usar cantidades algo mayores —gastables a propósito— para que el receptor las mantenga en su wallet y, al gastarlas, revele qué UTXOs son suyos. Por eso una salida pequeña por encima del umbral técnico merece atención, aunque no sea concluyente.",
penalty: weights.dust,
});
deductions += weights.dust;
} else {
checks.push({
id:"dust", label:"Outputs de dust detectados", certainty:"CERTEZA", pass:true,
actionability: "no_corregible",
detail: "Sin outputs de dust ni salidas inusualmente pequeñas (según el umbral de cada tipo de salida).",
didactic: "Un ataque de dust envía cantidades mínimas a múltiples direcciones. Cuando el receptor gasta ese dust combinándolo con otros UTXOs, revela qué UTXOs pertenecen al mismo wallet. Es una técnica de surveillance.",
penalty: weights.dust, informational: true,
});
}
// ── 10. Change detection — señales combinadas ─────────────────────
let changeSignals = 0;