diff --git a/dashboard.html b/dashboard.html index f792bb7..3297cde 100644 --- a/dashboard.html +++ b/dashboard.html @@ -141,6 +141,170 @@ })), }; + // ── Entity Index — direcciones de entidades conocidas ──────────── + // Embebido, sin consultas externas. Lookup O(1). + // OFAC: lista de sanciones (penaliza). Mining: pools (informativo). + // Fuentes: OFAC SDN list, mempool.space coinbase tags, bitcoin-data. + const ENTITY_INDEX = new Map([ + // ─── OFAC — entidades sancionadas (crítico) ─── + ["3K35dyL85fR9ht7UgzPfd1gLRRXQtNTqE3",{name:"Blender.io",cat:"ofac"}], + ["3Q5dGfLKkWqWSwYtbMUyc8xGjN5LrRviK4",{name:"Blender.io",cat:"ofac"}], + ["3EPqGUw2q89pwPZ1UF8FJspE2AyojSTjdu",{name:"Blender.io",cat:"ofac"}], + ["3LhnVMcBq4gsR7aDaRr9XmUo17CuYBV4FN",{name:"Blender.io",cat:"ofac"}], + ["3F6bbvS1krsc1qR8FsbTDfYQyvkMm3QvmR",{name:"Blender.io",cat:"ofac"}], + ["3JHMz3mTna1gVCZSPp8NgRFiY7phkv5mA8",{name:"Blender.io",cat:"ofac"}], + ["32DaxSzUhLBHY2WGSWQYiBSHnRsfQZrrRp",{name:"Blender.io",cat:"ofac"}], + ["3MTRvM5QrYZHKo8gh5qKcrPK3RLjxcDCZE",{name:"Blender.io",cat:"ofac"}], + ["34pFGsSYbWEritXncW9unZtQQE9dKSvKku",{name:"Blender.io",cat:"ofac"}], + ["38ncxqt932N9CcfNfYuHGZgCyR85hDkWBW",{name:"Blender.io",cat:"ofac"}], + ["3MD3riFB6U8PykypF6qkvSj8R2SGdUDPn3",{name:"Blender.io",cat:"ofac"}], + ["3JUwAS7seL3fh5hxWh9fu3HCiEzjuQLTfg",{name:"Blender.io",cat:"ofac"}], + ["3EUjqe9UpmyXCFd6jeu69hoTzndMRfxw9M",{name:"Blender.io",cat:"ofac"}], + ["3QEjBiPzw6WZUL4MYMmMU6DY1Y25aVbpQu",{name:"Blender.io",cat:"ofac"}], + ["3N3YSDvp4cbhEgNGabQxTN39kEzJmwG8Ah",{name:"Blender.io",cat:"ofac"}], + ["3J19qffPT6mxQUcV6k5yVURGZtdhpdGr4y",{name:"Blender.io",cat:"ofac"}], + ["33KKjn4exdBJQkTtdWxqpdVsWxrw3LareG",{name:"Blender.io",cat:"ofac"}], + ["3GSXNXzyCDoQ1Rhsc7F1jjjFe7DGcHHdcM",{name:"Blender.io",cat:"ofac"}], + ["3QJyT8nThEQakbfqgX86YjCK1Sp9hfNCUW",{name:"Blender.io",cat:"ofac"}], + ["35hh9dg3wSvUJz9vFk1FsezLE5Fx3Hudk2",{name:"Blender.io",cat:"ofac"}], + ["3NDzzVxiLBUs1WPvVGRfCYDTAD2Ua2PvW4",{name:"Blender.io",cat:"ofac"}], + ["3DCCgmyKozcZkFBzYb1A2x8abZCpAUTPPk",{name:"Blender.io",cat:"ofac"}], + ["3MvQ4gThF4mmuo49p4dBNchcmFHBRZnYfx",{name:"Blender.io",cat:"ofac"}], + ["3FBgeJdhiBe22UoSpp51Vd8dPHVa2A4wZX",{name:"Blender.io",cat:"ofac"}], + ["3HQDRyzwm82MFmLWtmyikDM9JQEtVT6vAp",{name:"Blender.io",cat:"ofac"}], + ["31t4nEpcwyQJT1VuXdAoQZTT5givRDPsNP",{name:"Blender.io",cat:"ofac"}], + ["39AALn7eTjdPzLb99hHhD6F7J8QWB3R2Rd",{name:"Blender.io",cat:"ofac"}], + ["3LDbNuDkKmLae5r3a5icPA5CQg2Y8F7ogW",{name:"Blender.io",cat:"ofac"}], + ["3JLyyLbwciWAC6re87D7mRknXakR4YbnUd",{name:"Blender.io",cat:"ofac"}], + ["3ANWhUnHujdwbw2jEuGSRH6bvFsD9BqEy9",{name:"Blender.io",cat:"ofac"}], + ["32fbAZMTaQxNd2fAue1PgsiPgWfcsHBQQt",{name:"Blender.io",cat:"ofac"}], + ["3HupEUfKmMhvhXqf8TMoPAyqDcRC1kpe65",{name:"Blender.io",cat:"ofac"}], + ["34kEYgpijvCmjvahRXXQEnBH76UGJVx2wg",{name:"Blender.io",cat:"ofac"}], + ["3GYbbYkvqvjF5oYhaKCgQYCvcVE1JENk6J",{name:"Blender.io",cat:"ofac"}], + ["3BazbaTP8ELJUEfPBV9z5HXEdgBziV9p7W",{name:"Blender.io",cat:"ofac"}], + ["3GMfGEDYMTq9G8dEHet1zLtUFJwYwSNa3Y",{name:"Blender.io",cat:"ofac"}], + ["38LjCapRrJEW7w2zwbyS15P9D9UGPjWS44",{name:"Blender.io",cat:"ofac"}], + ["36XqYWGvUQwBrYLRVuegN4pJJJSPWL1WEu",{name:"Blender.io",cat:"ofac"}], + ["37g6WgqedzZx6nx51tYgssNG8Hnknyj5nL",{name:"Blender.io",cat:"ofac"}], + ["3QAdoc1rDCt8dii1GVPJXvvK6CEJLzCRZw",{name:"Blender.io",cat:"ofac"}], + ["32PsiT8itBrEF84ebdaF82yBUEcz5Wc6uY",{name:"Blender.io",cat:"ofac"}], + ["3B4G1M8eF3cThbeMwhEWkKzczw9QoNTGak",{name:"Blender.io",cat:"ofac"}], + ["34ETiHfQWEYFCCaXmEeQWVmhFH5vz2JMvd",{name:"Blender.io",cat:"ofac"}], + ["3PyzSbFj3hbQQjTzDzyLSgvFVDjB7yw4Cj",{name:"Blender.io",cat:"ofac"}], + ["15PggTG7YhJKiE6B16vkKzA1YDTZipXEX4",{name:"Blender.io",cat:"ofac"}], + ["bc1qq7p0es3dv5hcynjjf40f2xjjr6qp5py47d2f6n847vduuq9gvnyq7y9ecd",{name:"Sinbad",cat:"ofac"}], + ["1JHdQHkBZiim1cb4hyUh2PbzEbbg6z2TrF",{name:"Sinbad",cat:"ofac"}], + ["3Lpoy53K625zVeE47ZasiG5jGkAxJ27kh1",{name:"Garantex",cat:"ofac"}], + ["12HQDsicffSBaYdJ6BhnE22sfjTESmmzKx",{name:"Suex",cat:"ofac"}], + ["1L4ncif9hh9TnUveqWq77HfWWt6CJWtrnb",{name:"Suex",cat:"ofac"}], + ["13mnk8SvDGqsQTHbiGiHBXqtaQCUKfcsnP",{name:"Suex",cat:"ofac"}], + ["1Edue8XZCWNoDBNZgnQkCCivDyr9GEo4x6",{name:"Suex",cat:"ofac"}], + ["1ECeZBxCVJ8Wm2JSN3Cyc6rge2gnvD3W5K",{name:"Suex",cat:"ofac"}], + ["1J9oGoAiHeRfeMZeUnJ9W7RpV55CdKtgYE",{name:"Suex",cat:"ofac"}], + ["1295rkVyNfFpqZpXvKGhDqwhP1jZcNNDMV",{name:"Suex",cat:"ofac"}], + ["1LiNmTUPSJEd92ZgVJjAV3RT9BzUjvUCkx",{name:"Suex",cat:"ofac"}], + ["1LrxsRd7zNuxPJcL5rttnoeJFy1y4AffYY",{name:"Suex",cat:"ofac"}], + ["1KUUJPkyDhamZXgpsyXqNGc3x1QPXtdhgz",{name:"Suex",cat:"ofac"}], + ["1CF46Rfbp97absrs7zb7dFfZS6qBXUm9EP",{name:"Suex",cat:"ofac"}], + ["1Df883c96LVauVsx9FEgnsourD8DELwCUQ",{name:"Suex",cat:"ofac"}], + ["bc1qdt3gml5z5n50y5hm04u2yjdphefkm0fl2zdj68",{name:"Suex",cat:"ofac"}], + ["1B64QRxfaa35MVkf7sDjuGUYAP5izQt7Qi",{name:"Suex",cat:"ofac"}], + ["3E7YbpXuhh3CWFks1jmvWoV8y5DvsfzE6n",{name:"Chatex",cat:"ofac"}], + ["3NRJ8aXdUiZdHaiFX9ePX3DhGHzcEi14Fq",{name:"Chatex",cat:"ofac"}], + ["3K7PMJyMNVnxqsfpmK9r9nJDtzDw9wNwNV",{name:"Chatex",cat:"ofac"}], + ["3H3rh85qPaGLy2w6618yZNaH7i8asHv46B",{name:"Chatex",cat:"ofac"}], + ["3MTrJTFhYK9v1C6pjHtuweZSopfZa4b1wb",{name:"Chatex",cat:"ofac"}], + ["347QFbejDBdMZFTxpmn6evvvqyXiqZTCd7",{name:"Chatex",cat:"ofac"}], + ["33xWfziVZesgo83U5izdNCBVTnrtBpSwK7",{name:"Chatex",cat:"ofac"}], + ["32wdqwX3zCEX3DhAVEcKwXCEGdzgBnx1R9",{name:"Chatex",cat:"ofac"}], + ["3N9YcPBDky9UsMx1RTk33tL4jDkZfSnsPk",{name:"Chatex",cat:"ofac"}], + ["bc1q90zrdysy4flyacw7hsury3ajs9yzwtwp6guqpypx94w0d3p58hysvz6pde",{name:"Chatex",cat:"ofac"}], + ["bc1qw7vfgv3r5vnehafl0y95sclg3uqsj87wxs9ad628yjjcq33cwessr6ndyw",{name:"Chatex",cat:"ofac"}], + ["bc1q86tl9255vg5wldamfymaaz36uqxzm30gs7fhkljvzdlt9t38s3lqgdwdfq",{name:"Chatex",cat:"ofac"}], + ["3M7CGBPUJwXXSroWuZ6H5jiprdKCyf7V5M",{name:"Chatex",cat:"ofac"}], + ["34kWCKF2wCbe6uinit2uL4ND6d8yxsuxKM",{name:"Chatex",cat:"ofac"}], + ["bc1qe95l438kzjcvnsm3kn8n5augf9gpctdlhsq7f7hpnkyvlr7rc7cqupapf7",{name:"Chatex",cat:"ofac"}], + ["32VgTk8kGvBsqkHhkvtNooGdtqZm46jTVo",{name:"Chatex",cat:"ofac"}], + ["3NPognMSbzyA2JYW2fpkVKWyBMi2XTq2Zt",{name:"Chatex",cat:"ofac"}], + ["3MzLtBQ4Lz9J6w4Qu55TktgxFKZwxYWrP6",{name:"Chatex",cat:"ofac"}], + ["36YGN5dGzqrxMomTHdkT6cYVMnWBw8S7hD",{name:"Chatex",cat:"ofac"}], + ["bc1q4rzdtlt0uslyw86cp29sctl6ct29g9a95cuup7pn5md9ddj7xgmqpp5m73",{name:"Chatex",cat:"ofac"}], + ["39KQvziHwUe2vddbpfC5WkQEV72qbQhxuh",{name:"Chatex",cat:"ofac"}], + ["3Qw9Fn19gCnga9LfHfpM99aGzuqxBNjR2i",{name:"Chatex",cat:"ofac"}], + ["1EfMVkxQQuZfBdocpJu6RUsCJvenQWbQyE",{name:"Lazarus Group",cat:"ofac"}], + ["17UVSMegvrzfobKC82dHXpZLtLcqzW9stF",{name:"Lazarus Group",cat:"ofac"}], + ["39eboeqYNFe2VoLC3mUGx4dh6GNhLB3D2q",{name:"Lazarus Group",cat:"ofac"}], + ["39fhoB2DohisGBbHvvfmkdPdShT75CNHdX",{name:"Lazarus Group",cat:"ofac"}], + ["3E6rY4dSCDW6y2bzJNwrjvTtdmMQjB6yeh",{name:"Lazarus Group",cat:"ofac"}], + ["3EeR8FbcPbkcGj77D6ttneJxmsr3Nu7KGV",{name:"Lazarus Group",cat:"ofac"}], + ["3HQRveQzPifZorZLDXHernc5zjoZax8U9f",{name:"Lazarus Group",cat:"ofac"}], + ["3JXKQ81JzBqVbB8VHdV9Jtd7auWokkdPgY",{name:"Lazarus Group",cat:"ofac"}], + ["3KHfXU24Bt3YD5Ef4J7uNp2buCuhrxfGen",{name:"Lazarus Group",cat:"ofac"}], + ["3LbDu1rUXHNyiz4i8eb3KwkSSBMf7C583D",{name:"Lazarus Group",cat:"ofac"}], + ["3MN8nYo1tt5hLxMwMbxDkXWd7Xu522hb9P",{name:"Lazarus Group",cat:"ofac"}], + ["3N6WeZ6i34taX8Ditser6LKWBcXmt2XXL4",{name:"Lazarus Group",cat:"ofac"}], + ["134r8iHv69xdT6p5qVKTsHrcUEuBVZAYak",{name:"Lazarus Group",cat:"ofac"}], + ["15YK647qtoZQDzNrvY6HJL6QwXduLHfT28",{name:"Lazarus Group",cat:"ofac"}], + ["1PfwHNxUnkpfkK9MKjMqzR3Xq3KCtq9u17",{name:"Lazarus Group",cat:"ofac"}], + ["14kqryJUxM3a7aEi117KX9hoLUw592WsMR",{name:"Lazarus Group",cat:"ofac"}], + ["1F2Gdug9ib9NQMhKMGGJczzMk5SuENoqrp",{name:"Lazarus Group",cat:"ofac"}], + ["3F2sZ4jbhvDKQdGbHYPC6ZxFXEau2m5Lqj",{name:"Lazarus Group",cat:"ofac"}], + ["1AXUTu9y3H8w4wYx4BjyFWgRhZKDhmcMrn",{name:"Lazarus Group",cat:"ofac"}], + ["1Hn9ErTCPRP6j5UDBeuXPGuq5RtRjFJxJQ",{name:"Lazarus Group",cat:"ofac"}], + // ─── Mining pools (informativo) ─── + ["1KFHE7w8BhaENAswwryaoccDb6qcT6DbYY",{name:"F2Pool",cat:"mining"}], + ["bc1qf274x7penhcd8hsv3jcmwa5xxzjl2a6pa9pxwm",{name:"F2Pool",cat:"mining"}], + ["bc1q7wedv4zdu5smt3shljpu5mgns48jn299mukymc",{name:"F2Pool",cat:"mining"}], + ["1KGG9kvV5zXiqyQAMfY32sGt9eFLMmgpgX",{name:"F2Pool",cat:"mining"}], + ["12KKDt4Mj7N5UAkQMN7LtPZMayenXHa8KL",{name:"Foundry USA",cat:"mining"}], + ["1FFxkVijzvUPUeHgkFjBk2Qw8j3wQY2cDw",{name:"Foundry USA",cat:"mining"}], + ["bc1qxhmdufsvnuaaaer4ynz88fspdsxq2h9e9cetdj",{name:"Foundry USA",cat:"mining"}], + ["bc1p8k4v4xuz55dv49svzjg43qjxq2whur7ync9tm0xgl5t4wjl9ca9snxgmlt",{name:"Foundry USA",cat:"mining"}], + ["bc1qwzrryqr3ja8w7hnja2spmkgfdcgvqwp5swz4af4ngsjecfz0w0pqud7k38",{name:"Foundry USA",cat:"mining"}], + ["1PuJjnF476W3zXfVYmJfGnouzFDAXakkL4",{name:"ViaBTC",cat:"mining"}], + ["12dRugNcdxK39288NjcDV4GX7rMsKCGn6B",{name:"Antpool",cat:"mining"}], + ["15kiNKfDWsq7UsPg87UwxA8rVvWAjzRkYS",{name:"Antpool",cat:"mining"}], + ["16MdTdqmXusauybtXTmFEW4GNFPPgGxQYE",{name:"Antpool",cat:"mining"}], + ["16kUc5B48qnASbxeZTisCqTNx6G3DPXuKn",{name:"Antpool",cat:"mining"}], + ["17gVZssumiJqYMCHozHKXGyaAvyu6NCX6V",{name:"Antpool",cat:"mining"}], + ["1AJQ3jXhUF8WiisEcuVd8Xmfq4QJ7n1SdL",{name:"Antpool",cat:"mining"}], + ["1BWW3pg5jb6rxebrNeo9TATarwJ1rthnoe",{name:"Antpool",cat:"mining"}], + ["1CyB8GJNEsNVXtPutB36nrDY3fMXBTzXSX",{name:"Antpool",cat:"mining"}], + ["1D4UZG4qo8bF1MuZHSEyBHRZaxT8inatXS",{name:"Antpool",cat:"mining"}], + ["1DDXyKUT6q3H9e5QXm2Gv6BNNWgztFG55g",{name:"Antpool",cat:"mining"}], + ["1Dek9ArRHb9tyWb9gaaX8SWmkfi5V7U5Y6",{name:"Antpool",cat:"mining"}], + ["1DyR7HPQWjM6Zrnk7SzHVY2GEpXRGNNH9o",{name:"Antpool",cat:"mining"}], + ["1FdJkPdpXtK3t5utZHJAop3saLZWfPfgak",{name:"Antpool",cat:"mining"}], + ["1GRcX882sdBYCAWyG99iF2oz7j3nYzXhLM",{name:"Antpool",cat:"mining"}], + ["1Gp7iCzDGMZiV55Kt8uKsux6VyoHe1aJaN",{name:"Antpool",cat:"mining"}], + ["1H3u6R813MHGYhmGW6v86EYYriawRtACYD",{name:"Antpool",cat:"mining"}], + ["1JBVrhSSDrZrRmm4RnoWouqgGGqJMvWHi8",{name:"Antpool",cat:"mining"}], + ["1JwUDWVSbAY5NeCBJhxQk1E8AfETfZuPj4",{name:"Antpool",cat:"mining"}], + ["1K8PNogxBZ6ts532DZnzxdbjgzJLjLdXqz",{name:"Antpool",cat:"mining"}], + ["1LTGvTjDxiy5S9YcKEE9Lb7xSpZcPSqinw",{name:"Antpool",cat:"mining"}], + ["1NS4gbx1G2D5rc9PnvVsPys12nKxGiQg72",{name:"Antpool",cat:"mining"}], + ["1Nh7uHdvY6fNwtQtM1G5EZAFPLC33B59rB",{name:"Antpool",cat:"mining"}], + ["1Sjj2cPC3rTWcSTEYDeu2f3BavLosog4T",{name:"Antpool",cat:"mining"}], + ["1jLVpwtNMfXWaHY4eiLDmGuBxokYLgv1X",{name:"Antpool",cat:"mining"}], + ["39C7fxSzEACPjM78Z7xdPxhf7mKxJwvfMJ",{name:"Antpool",cat:"mining"}], + ["3FaYYQF6wCMUB9NCeRe4tUp1zZx8qqM7H1",{name:"Antpool",cat:"mining"}], + ["15MdAHnkxt9TMC2Rj595hsg8Hnv693pPBB",{name:"MARA Pool",cat:"mining"}], + ["1A32KFEX7JNPmU1PVjrtiXRrTQcesT3Nf1",{name:"MARA Pool",cat:"mining"}], + ["3D72db1KMCnj7FL7MBsmxTw81z2bVu4UN5",{name:"MARA Pool",cat:"mining"}], + ["3LC8dDKyBsrWPfzhXyt7aAyjXxGYkfDdHu",{name:"MARA Pool",cat:"mining"}], + ["1AqTMY7kmHZxBuLUR5wJjPFUvqGs23sesr",{name:"Braiins Pool",cat:"mining"}], + ["1CK6KHY6MHgYvmRQ4PAafKYDrg1ejbH1cE",{name:"Braiins Pool",cat:"mining"}], + ["1MkCDCzHpBsYQivp8MxjY5AkTGG1f2baoe",{name:"Luxor",cat:"mining"}], + ["39bitUyBcUu3y3hRTtYprKbTp712t4ZWqK",{name:"Luxor",cat:"mining"}], + ["32BfKjhByDSxx3BM5vUkQ3NQq9csZR6nt6",{name:"Luxor",cat:"mining"}], + ["37dvwZZoT3D7RXpTCpN2yKzMmNs2i2Fd1n",{name:"Ocean Mining",cat:"mining"}], + ["bc1qvfzssz36y4gxcg9gh234rzem9k0vrdlx4kq5sg",{name:"NiceHash",cat:"mining"}], + ["14yfxkcpHnju97pecpM7fjuTkVdtbkcfE6",{name:"Bitfury",cat:"mining"}], + ["1AcAj9p6zJn4xLXdvmdiuPCtY7YkBPTAJo",{name:"Bitfury",cat:"mining"}], + ["1FeDtFhARLxjKUPPkQqEBL78tisenc9znS",{name:"Bitfury",cat:"mining"}], + ["1Nd99aNgYWpKkqcqSMgWtdtVDadewAS5F7",{name:"Bitfury",cat:"mining"}], + ]); + // ── Wallet fingerprinting — señales combinadas ────────────────────── function detectWallets(tx, isBip69Shared) { const results = []; @@ -270,7 +434,7 @@ input_reuse: 25, input_type_mixing: 14, output_type_mismatch: 8, round_numbers: 10, rbf: 5, peeling: 8, unnecessary_input: 12, dust: 8, change_detection: 10, - wallet_fingerprint: 6, batch_payment: 4, + wallet_fingerprint: 6, batch_payment: 4, entity_ofac: 20, }; let deductions = 0; @@ -663,6 +827,47 @@ penalty: 0, informational: true, }); + // ── 16. Detección de entidades conocidas ────────────────────────── + // Cruza direcciones de inputs y outputs contra el ENTITY_INDEX embebido. + const allTxAddrs = [ + ...tx.vin.map(v => ({ addr: v.prevout?.scriptpubkey_address, side: "input" })), + ...tx.vout.map(v => ({ addr: v.scriptpubkey_address, side: "output" })), + ].filter(x => x.addr); + const ofacHits = []; + const miningHits = []; + for (const { addr, side } of allTxAddrs) { + const hit = ENTITY_INDEX.get(addr); + if (!hit) continue; + if (hit.cat === "ofac") ofacHits.push({ ...hit, addr, side }); + if (hit.cat === "mining") miningHits.push({ ...hit, addr, side }); + } + + // OFAC — crítico, penaliza + if (ofacHits.length > 0) { + const names = [...new Set(ofacHits.map(h => h.name))].join(", "); + const sides = [...new Set(ofacHits.map(h => h.side))]; + checks.push({ + id:"entity_ofac", label:"Dirección en lista de sanciones OFAC", certainty:"CERTEZA", pass:false, + actionability: "no_corregible", + detail: `Una o más direcciones de esta transacción (${sides.join(" y ")}) aparecen en la lista de sanciones OFAC: ${names}. Esto no implica que hayas actuado ilegalmente, pero tus fondos han estado en contacto con una entidad sancionada internacionalmente. Los exchanges con KYC pueden usar este dato para bloquear o congelar depósitos relacionados.`, + didactic: "La OFAC (Office of Foreign Assets Control, EE.UU.) mantiene una lista de direcciones de entidades sancionadas: mixers como Blender.io o Sinbad, exchanges como Garantex o Suex, y grupos como Lazarus. La lista es de dominio público y la usan los servicios regulados. Una coincidencia es un hecho verificable, no una probabilidad.", + penalty: weights.entity_ofac, + }); + deductions += weights.entity_ofac; + } + + // Mining pools — informativo, cierra el rastro + if (miningHits.length > 0) { + const names = [...new Set(miningHits.map(h => h.name))].join(", "); + checks.push({ + id:"entity_mining", label:"Origen en pool de minería", certainty:"informativo", pass:true, + actionability: "no_corregible", + detail: `Una o más direcciones provienen de un pool de minería conocido: ${names}. Si es un input, estas monedas proceden de una recompensa de minado — no tienen historial previo que rastrear.`, + didactic: "Las direcciones de coinbase de los pools de minería son públicas. Recibir fondos directamente de un pool indica actividad de minería y cierra el rastro de procedencia: no hay transacciones anteriores porque las monedas se crearon en ese bloque.", + penalty: 0, informational: true, + }); + } + // ── Score compuesto ─────────────────────────────────────────────── const maxPossible = Object.values(weights).reduce((a,b)=>a+b,0); const score = Math.max(0, Math.min(100, Math.round(100 - (deductions / maxPossible) * 100)));