diff --git a/public/analytics.js b/public/analytics.js index 091ab0e..ce1836a 100644 --- a/public/analytics.js +++ b/public/analytics.js @@ -81,7 +81,7 @@ - + @@ -772,6 +772,12 @@ async function renderCollisionTab(el, data) { el.innerHTML = ` +
+

⚠️ Inconsistent Hash Sizes

+

Nodes that have sent adverts with varying hash sizes — likely running firmware with a known bug (pre-1.14.1).

+
Loading…
+
+

1-Byte Hash Usage Matrix

Click a cell to see which nodes share that prefix. Green = available, yellow = taken, red = collision.

@@ -785,6 +791,33 @@ `; let allNodes = []; try { const nd = await api('/nodes?limit=2000' + RegionFilter.regionQueryString(), { ttl: CLIENT_TTL.nodeList }); allNodes = nd.nodes || []; } catch {} + + // Render inconsistent hash sizes + const inconsistent = allNodes.filter(n => n.hash_size_inconsistent); + const ihEl = document.getElementById('inconsistentHashList'); + if (ihEl) { + if (!inconsistent.length) { + ihEl.innerHTML = '
✅ No inconsistencies detected — all nodes are reporting consistent hash sizes.
'; + } else { + ihEl.innerHTML = ` + + ${inconsistent.map(n => { + const roleColor = window.ROLE_COLORS?.[n.role] || '#6b7280'; + const prefix = n.hash_size ? n.public_key.slice(0, n.hash_size * 2).toUpperCase() : '?'; + const sizes = (n.hash_sizes_seen || []).map(s => s + 'B').join(', '); + return ` + + + + + + `; + }).join('')} +
NodeRoleCurrent HashSizes SeenStatus
${esc(n.name || n.public_key.slice(0, 12))}${n.role}${prefix} (${n.hash_size || '?'}B)${sizes}⚠️ variable
+

${inconsistent.length} node${inconsistent.length > 1 ? 's' : ''} affected. Click a node name to see which adverts have different hash sizes.

`; + } + } + renderHashMatrix(data.topHops, allNodes); renderCollisions(data.topHops, allNodes); }