Aggiunge visualizzazione chiavi compresse/non compresse in report HTML
This commit is contained in:
@@ -75,6 +75,20 @@ class P2PKDatabaseViewer:
|
|||||||
stats['unspent_value_btc'] = unspent_sat / 100000000.0
|
stats['unspent_value_btc'] = unspent_sat / 100000000.0
|
||||||
stats['unspent_value_sat'] = int(unspent_sat)
|
stats['unspent_value_sat'] = int(unspent_sat)
|
||||||
|
|
||||||
|
# Conta chiavi compresse vs non compresse
|
||||||
|
cursor.execute('SELECT scriptpubkey FROM p2pk_addresses')
|
||||||
|
all_scripts = cursor.fetchall()
|
||||||
|
compressed_count = 0
|
||||||
|
uncompressed_count = 0
|
||||||
|
for (script,) in all_scripts:
|
||||||
|
if script and script.startswith('41') and len(script) == 134:
|
||||||
|
uncompressed_count += 1
|
||||||
|
elif script and script.startswith('21') and len(script) == 70:
|
||||||
|
compressed_count += 1
|
||||||
|
|
||||||
|
stats['compressed_count'] = compressed_count
|
||||||
|
stats['uncompressed_count'] = uncompressed_count
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"⚠️ Errore nel calcolo statistiche: {e}")
|
print(f"⚠️ Errore nel calcolo statistiche: {e}")
|
||||||
import traceback
|
import traceback
|
||||||
@@ -91,7 +105,9 @@ class P2PKDatabaseViewer:
|
|||||||
'unique_txs': 0,
|
'unique_txs': 0,
|
||||||
'unspent_count': 0,
|
'unspent_count': 0,
|
||||||
'unspent_value_btc': 0.0,
|
'unspent_value_btc': 0.0,
|
||||||
'unspent_value_sat': 0
|
'unspent_value_sat': 0,
|
||||||
|
'compressed_count': 0,
|
||||||
|
'uncompressed_count': 0
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.close()
|
conn.close()
|
||||||
@@ -140,7 +156,8 @@ class P2PKDatabaseViewer:
|
|||||||
|
|
||||||
rows_html = []
|
rows_html = []
|
||||||
for row in p2pk_data:
|
for row in p2pk_data:
|
||||||
pubkey = self.extract_pubkey_from_script(row[4])
|
scriptpubkey = row[4]
|
||||||
|
pubkey = self.extract_pubkey_from_script(scriptpubkey)
|
||||||
txid_short = row[2][:16] if len(row[2]) > 16 else row[2]
|
txid_short = row[2][:16] if len(row[2]) > 16 else row[2]
|
||||||
timestamp_str = datetime.fromtimestamp(row[6]).strftime('%Y-%m-%d %H:%M') if row[6] else 'N/A'
|
timestamp_str = datetime.fromtimestamp(row[6]).strftime('%Y-%m-%d %H:%M') if row[6] else 'N/A'
|
||||||
# row[5] è già in satoshi, lo convertiamo in BTC dividendo per 100000000
|
# row[5] è già in satoshi, lo convertiamo in BTC dividendo per 100000000
|
||||||
@@ -152,8 +169,19 @@ class P2PKDatabaseViewer:
|
|||||||
utxo_status = '🟢 NON SPESO' if is_unspent else '🔴 SPESO'
|
utxo_status = '🟢 NON SPESO' if is_unspent else '🔴 SPESO'
|
||||||
utxo_class = 'unspent' if is_unspent else 'spent'
|
utxo_class = 'unspent' if is_unspent else 'spent'
|
||||||
|
|
||||||
|
# Determina se la chiave è compressa o non compressa
|
||||||
|
if scriptpubkey and scriptpubkey.startswith('41') and len(scriptpubkey) == 134:
|
||||||
|
key_type = 'uncompressed'
|
||||||
|
key_type_badge = '<span class="key-type-badge uncompressed">📜 Non Compressa (65 bytes)</span>'
|
||||||
|
elif scriptpubkey and scriptpubkey.startswith('21') and len(scriptpubkey) == 70:
|
||||||
|
key_type = 'compressed'
|
||||||
|
key_type_badge = '<span class="key-type-badge compressed">📦 Compressa (33 bytes)</span>'
|
||||||
|
else:
|
||||||
|
key_type = 'unknown'
|
||||||
|
key_type_badge = '<span class="key-type-badge unknown">❓ Sconosciuta</span>'
|
||||||
|
|
||||||
row_html = f'''
|
row_html = f'''
|
||||||
<tr class="{utxo_class}">
|
<tr class="{utxo_class} {key_type}">
|
||||||
<td>{row[0]}</td>
|
<td>{row[0]}</td>
|
||||||
<td><span class="block">{row[1]}</span></td>
|
<td><span class="block">{row[1]}</span></td>
|
||||||
<td>
|
<td>
|
||||||
@@ -163,7 +191,8 @@ class P2PKDatabaseViewer:
|
|||||||
<td>{row[3]}</td>
|
<td>{row[3]}</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="pubkey">
|
<div class="pubkey">
|
||||||
{pubkey}
|
{key_type_badge}
|
||||||
|
<div style="margin-top: 5px;">{pubkey}</div>
|
||||||
<button class="copy-btn" onclick="copyToClipboard('{pubkey}')">📋</button>
|
<button class="copy-btn" onclick="copyToClipboard('{pubkey}')">📋</button>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@@ -462,6 +491,33 @@ class P2PKDatabaseViewer:
|
|||||||
tr.spent {{
|
tr.spent {{
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
.key-type-badge {{
|
||||||
|
padding: 4px 10px;
|
||||||
|
border-radius: 15px;
|
||||||
|
font-size: 0.8em;
|
||||||
|
font-weight: bold;
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.key-type-badge.uncompressed {{
|
||||||
|
background: #cfe2ff;
|
||||||
|
color: #084298;
|
||||||
|
border: 1px solid #9ec5fe;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.key-type-badge.compressed {{
|
||||||
|
background: #d1e7dd;
|
||||||
|
color: #0a3622;
|
||||||
|
border: 1px solid #a3cfbb;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.key-type-badge.unknown {{
|
||||||
|
background: #f8d7da;
|
||||||
|
color: #58151c;
|
||||||
|
border: 1px solid #f1aeb5;
|
||||||
|
}}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -505,6 +561,14 @@ class P2PKDatabaseViewer:
|
|||||||
<div class="label" style="color: #0c5460;">💎 Valore Non Speso</div>
|
<div class="label" style="color: #0c5460;">💎 Valore Non Speso</div>
|
||||||
<div class="value" style="color: #0c5460;">{stats['unspent_value_btc']:.8f} BTC</div>
|
<div class="value" style="color: #0c5460;">{stats['unspent_value_btc']:.8f} BTC</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="stat-card" style="background: #cfe2ff;">
|
||||||
|
<div class="label" style="color: #084298;">📜 Chiavi Non Compresse</div>
|
||||||
|
<div class="value" style="color: #084298;">{stats['uncompressed_count']:,}</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card" style="background: #d1e7dd;">
|
||||||
|
<div class="label" style="color: #0a3622;">📦 Chiavi Compresse</div>
|
||||||
|
<div class="value" style="color: #0a3622;">{stats['compressed_count']:,}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
@@ -518,6 +582,12 @@ class P2PKDatabaseViewer:
|
|||||||
<button class="filter-btn spent-filter" onclick="filterByStatus('spent')">🔴 Solo Spesi</button>
|
<button class="filter-btn spent-filter" onclick="filterByStatus('spent')">🔴 Solo Spesi</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="filter-buttons" style="margin-top: 10px;">
|
||||||
|
<button class="filter-btn" onclick="filterByKeyType('all-keys')">🔑 Tutti i Tipi</button>
|
||||||
|
<button class="filter-btn" onclick="filterByKeyType('uncompressed')">📜 Solo Non Compresse</button>
|
||||||
|
<button class="filter-btn" onclick="filterByKeyType('compressed')">📦 Solo Compresse</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
{self._generate_table_html(p2pk_data)}
|
{self._generate_table_html(p2pk_data)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -581,6 +651,32 @@ class P2PKDatabaseViewer:
|
|||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
function filterByKeyType(keyType) {{
|
||||||
|
const table = document.getElementById('dataTable');
|
||||||
|
if (!table) return;
|
||||||
|
|
||||||
|
const tr = table.getElementsByTagName('tr');
|
||||||
|
|
||||||
|
// Aggiorna stato pulsanti del gruppo key-type
|
||||||
|
event.target.parentElement.querySelectorAll('.filter-btn').forEach(btn => {{
|
||||||
|
btn.classList.remove('active');
|
||||||
|
}});
|
||||||
|
event.target.classList.add('active');
|
||||||
|
|
||||||
|
// Filtra righe in base al tipo di chiave
|
||||||
|
for (let i = 1; i < tr.length; i++) {{
|
||||||
|
const row = tr[i];
|
||||||
|
|
||||||
|
if (keyType === 'all-keys') {{
|
||||||
|
row.style.display = '';
|
||||||
|
}} else if (keyType === 'uncompressed') {{
|
||||||
|
row.style.display = row.classList.contains('uncompressed') ? '' : 'none';
|
||||||
|
}} else if (keyType === 'compressed') {{
|
||||||
|
row.style.display = row.classList.contains('compressed') ? '' : 'none';
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
}}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user