feat: cierra las cinco heurísticas ausentes del repaso
La comisión como huella: una comisión absoluta redonda o una tarifa entera no salen de un estimador, salen de alguien que las escribió a mano. Informativo y sin penalizar, igual que RBF — castigarlo empujaría a elegir comisiones peores para disimular. Cambio con más de dos salidas, solo el caso inequívoco: si exactamente una salida comparte tipo con las entradas no hay nada que adivinar, y con más salidas la coincidencia por azar es todavía más improbable. POSIBLE, no PROBABLE, porque es una sola señal. Autoenvíos en el informe de wallet: solo cabe ahí, porque saber que todas las salidas son tuyas exige conocer el wallet entero. Avisa solo cuando ataron más de una dirección — mover una a otra no vincula nada nuevo.
This commit is contained in:
@@ -160,6 +160,44 @@ ok("se etiqueta como consolidación, con certeza y no como probable",
|
||||
ok("no se cobra dos veces: la penalización la lleva input_linkage",
|
||||
cu?.penalty === 0 && check(consol, "input_linkage")?.pass === false);
|
||||
|
||||
console.log("\n=== La comisión como huella (check nuevo) ===\n");
|
||||
|
||||
// Comisión absoluta redonda: nadie llega a 10.000 sats clavados con un
|
||||
// estimador, que calcula tarifa por tamaño y devuelve números feos.
|
||||
const feeRedonda = analyzeTx(TX(
|
||||
[IN(5000000, "v1_p2tr", "bc1pA")],
|
||||
[OUT(4990000, "v1_p2tr", "bc1pB")],
|
||||
{ fee: 10000, weight: 600 }
|
||||
));
|
||||
ok("detecta una comisión absoluta redonda",
|
||||
check(feeRedonda, "fee_fingerprint")?.pass === true &&
|
||||
/10000 sats exactos/.test(check(feeRedonda, "fee_fingerprint")?.detail || ""),
|
||||
check(feeRedonda, "fee_fingerprint")?.detail?.slice(0, 90));
|
||||
|
||||
// Tarifa entera: 20,00 sat/vB sale de teclear "20" en la casilla.
|
||||
const feeEntera = analyzeTx(TX(
|
||||
[IN(5000000, "v1_p2tr", "bc1pA")],
|
||||
[OUT(4996000, "v1_p2tr", "bc1pB")],
|
||||
{ fee: 3000, weight: 600 } // vsize 150 -> 20,00 sat/vB
|
||||
));
|
||||
ok("detecta una tarifa prácticamente entera",
|
||||
/prácticamente un número entero|sats exactos/.test(check(feeEntera, "fee_fingerprint")?.detail || ""),
|
||||
check(feeEntera, "fee_fingerprint")?.detail?.slice(0, 90));
|
||||
|
||||
// Un estimador automático deja números feos.
|
||||
const feeEstimada = analyzeTx(TX(
|
||||
[IN(5000000, "v1_p2tr", "bc1pA")],
|
||||
[OUT(4996873, "v1_p2tr", "bc1pB")],
|
||||
{ fee: 3127, weight: 601 }
|
||||
));
|
||||
ok("no ve huella donde hay un número feo de estimador",
|
||||
/sin forma de cifra elegida a mano/.test(check(feeEstimada, "fee_fingerprint")?.detail || ""),
|
||||
check(feeEstimada, "fee_fingerprint")?.detail?.slice(0, 90));
|
||||
|
||||
ok("la huella de comisión no penaliza (misma decisión que con RBF)",
|
||||
check(feeRedonda, "fee_fingerprint")?.penalty === 0 &&
|
||||
check(feeRedonda, "fee_fingerprint")?.informational === true);
|
||||
|
||||
console.log("\n=== Guardia de CoinJoin ===\n");
|
||||
|
||||
// Whirlpool: 5 entradas, 5 salidas de la misma denominación.
|
||||
|
||||
Reference in New Issue
Block a user