fix: cuadrar el denominador de la nota y ampliar la redondez; dos checks nuevos
El denominador de la nota incluía dos pesos que nunca restan (rbf, peeling) y excluía uno que sí (input_linkage, hasta 30), así que las deducciones podían superarlo en 17 puntos y dar negativo. Corregido en ambas direcciones, con los cortes de banda recalibrados a 79/54 para que ninguna transacción cambie de banda por el arreglo. 'Redondo' equivalía a 'múltiplo de 0,001 BTC' por dos condiciones redundantes, y se le escapaban pagos de 10.000 o 50.000 sats. Ahora se mide por ceros finales y la señal se gradúa. Dos checks nuevos. El de polvo avisaba de una vinculación futura y nunca miraba si estaba ocurriendo delante: ahora la detecta cuando el polvo se gasta junto a monedas normales. Y la consolidación pura (N entradas, 1 salida) no disparaba el check de inputs innecesarios; ahora se nombra, sin cobrarla dos veces porque input_linkage ya la penaliza. tests/test6.js cubre lo nuevo y la coherencia de la nota.
This commit is contained in:
+36
-3
@@ -19,11 +19,13 @@ const path = require("path");
|
||||
|
||||
const htmlPath = path.join(__dirname, "..", "dashboard.html");
|
||||
const lines = fs.readFileSync(htmlPath, "utf8").split("\n");
|
||||
const start = lines.findIndex(l => l.includes("function guessChangeOutput"));
|
||||
if (start === -1) { console.error("No se encuentra guessChangeOutput en dashboard.html"); process.exit(1); }
|
||||
// Se extrae desde roundness() porque guessChangeOutput depende de ella y de
|
||||
// ROUND_MIN. El corte de abajo es analyzeTx, la siguiente función del archivo.
|
||||
const start = lines.findIndex(l => l.includes("function roundness"));
|
||||
if (start === -1) { console.error("No se encuentra roundness en dashboard.html"); process.exit(1); }
|
||||
const end = lines.findIndex((l, i) => i > start && l.includes("function analyzeTx"));
|
||||
const src = lines.slice(start, end).join("\n");
|
||||
const guessChangeOutput = new Function(src + "\nreturn guessChangeOutput;")();
|
||||
const { guessChangeOutput, roundness } = new Function(src + "\nreturn { guessChangeOutput, roundness };")();
|
||||
|
||||
const IN = (v,t,a) => ({ prevout:{ value:v, scriptpubkey_type:t, scriptpubkey_address:a }, txid:"aa", vout:0 });
|
||||
const OUT = (v,t,a) => ({ value:v, scriptpubkey_type:t, scriptpubkey_address:a, scriptpubkey:"00" });
|
||||
@@ -85,5 +87,36 @@ T("CoinJoin: la guardia desactiva la heurística aunque haya señales",
|
||||
vout:[OUT(100000,"v1_p2tr","bc1pX"), OUT(99895000,"v0_p2wpkh","bc1qY")] },
|
||||
null, true);
|
||||
|
||||
// ── Redondez ────────────────────────────────────────────────────────────
|
||||
// La versión anterior era `v%1000000===0 || v%100000===0 || v%10000000===0`,
|
||||
// donde la primera y la tercera condición sobran (todo múltiplo de un millón
|
||||
// lo es de cien mil). Equivalía a "múltiplo de 0,001 BTC" y se le escapaban
|
||||
// pagos tan redondos como 10.000 o 50.000 sats.
|
||||
console.log("\n=== Redondez de las cifras ===\n");
|
||||
function R(sats, minimo) {
|
||||
const nivel = roundness(sats);
|
||||
const ok = nivel >= minimo;
|
||||
console.log(` ${ok ? "✓" : "✗"} ${String(sats).padStart(9)} sat = ${(sats/1e8).toFixed(8)} BTC -> nivel ${nivel} (mínimo esperado ${minimo})`);
|
||||
ok ? pass++ : fail++;
|
||||
}
|
||||
R(100000000, 4); // 1 BTC
|
||||
R( 10000000, 4); // 0,1 BTC
|
||||
R( 1000000, 3); // 0,01 BTC
|
||||
R( 100000, 3); // 0,001 BTC
|
||||
R( 250000, 2); // 0,0025 BTC — se escapaba antes
|
||||
R( 50000, 2); // 0,0005 BTC — se escapaba antes
|
||||
R( 10000, 2); // 0,0001 BTC — se escapaba antes
|
||||
|
||||
// Y lo que NO debe considerarse redondo.
|
||||
function NR(sats) {
|
||||
const nivel = roundness(sats);
|
||||
const ok = nivel < 2;
|
||||
console.log(` ${ok ? "✓" : "✗"} ${String(sats).padStart(9)} sat -> nivel ${nivel} (no debe llegar a 2)`);
|
||||
ok ? pass++ : fail++;
|
||||
}
|
||||
NR(123456);
|
||||
NR(99895000);
|
||||
NR(1234567);
|
||||
|
||||
console.log(`\n${pass} correctos, ${fail} fallos`);
|
||||
process.exit(fail === 0 ? 0 : 1);
|
||||
|
||||
Reference in New Issue
Block a user