From 7c7d457036eb36f091b017447ce3f31b8bd2be65 Mon Sep 17 00:00:00 2001 From: LaphoqueRC <91871936+LaphoqueRC@users.noreply.github.com> Date: Fri, 20 Mar 2026 07:26:41 +0300 Subject: [PATCH 1/8] add: hall of fame machine --- hall_of_fame_machine.py | 313 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 313 insertions(+) create mode 100644 hall_of_fame_machine.py diff --git a/hall_of_fame_machine.py b/hall_of_fame_machine.py new file mode 100644 index 00000000..3a16dc73 --- /dev/null +++ b/hall_of_fame_machine.py @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: MIT +# SPDX-License-Identifier: MIT + +from flask import Flask, request, jsonify, render_template_string +import sqlite3 +import json +from datetime import datetime + +app = Flask(__name__) + +DB_PATH = 'rustchain.db' + +def get_machine_details(fingerprint_hash): + """Get detailed machine information""" + with sqlite3.connect(DB_PATH) as conn: + conn.row_factory = sqlite3.Row + cursor = conn.cursor() + + # Get machine basic info + cursor.execute(''' + SELECT fingerprint_hash, machine_name, first_seen, + total_attestations, rust_score, fleet_rank + FROM hall_of_fame + WHERE fingerprint_hash = ? + ''', (fingerprint_hash,)) + machine = cursor.fetchone() + + if not machine: + return None + + # Get attestation history + cursor.execute(''' + SELECT epoch, rust_score, timestamp + FROM attestations + WHERE fingerprint_hash = ? + ORDER BY epoch DESC + LIMIT 50 + ''', (fingerprint_hash,)) + attestation_history = cursor.fetchall() + + # Get fleet averages for comparison + cursor.execute(''' + SELECT AVG(rust_score) as avg_score, + COUNT(*) as total_machines + FROM hall_of_fame + ''') + fleet_stats = cursor.fetchone() + + return { + 'machine': dict(machine), + 'attestation_history': [dict(row) for row in attestation_history], + 'fleet_stats': dict(fleet_stats) + } + +@app.route('/hall-of-fame/machine') +def machine_detail_page(): + machine_id = request.args.get('id') + if not machine_id: + return "Machine ID required", 400 + + machine_data = get_machine_details(machine_id) + if not machine_data: + return "Machine not found", 404 + + machine = machine_data['machine'] + history = machine_data['attestation_history'] + fleet_stats = machine_data['fleet_stats'] + + # Calculate performance metrics + if history: + recent_scores = [h['rust_score'] for h in history[:10]] + trend = "RISING" if len(recent_scores) > 1 and recent_scores[0] > recent_scores[-1] else "STABLE" + avg_recent = sum(recent_scores) / len(recent_scores) + else: + trend = "NO_DATA" + avg_recent = 0 + + html_template = ''' + + + + + + {{ machine.machine_name or machine.fingerprint_hash[:12] }} - Hall of Fame + + + +
+ < Back to Hall of Fame + +
+
+ {{ machine.machine_name or 'Machine #' + machine.fingerprint_hash[:8] }} +
+
{{ machine.fingerprint_hash }}
+
+ +
+
+
Rust Score
+
+ {{ "%.2f"|format(machine.rust_score) }} + {% if avg_recent > fleet_stats.avg_score %} + ABOVE FLEET AVG + {% else %} + BELOW FLEET AVG + {% endif %} +
+
+ +
+
Fleet Rank
+
#{{ machine.fleet_rank }} / {{ fleet_stats.total_machines }}
+
+ +
+
Total Attestations
+
{{ machine.total_attestations }}
+
+ +
+
First Seen
+
{{ machine.first_seen.split('T')[0] if machine.first_seen else 'Unknown' }}
+
+ +
+
Performance Trend
+
{{ trend }}
+
+ +
+
Fleet Average
+
{{ "%.2f"|format(fleet_stats.avg_score) }}
+
+
+ + {% if history %} +
+
Recent Attestation History
+ + + + + + + + + + + {% for h in history %} + + + + + + + {% endfor %} + +
EpochRust ScoreTimestampVariance
{{ h.epoch }}{{ "%.2f"|format(h.rust_score) }}{{ h.timestamp.split('T')[0] if h.timestamp else 'N/A' }} + {% set variance = h.rust_score - fleet_stats.avg_score %} + {% if variance > 0 %} + +{{ "%.2f"|format(variance) }} + {% else %} + {{ "%.2f"|format(variance) }} + {% endif %} +
+
+ {% endif %} +
+ + + ''' + + return render_template_string(html_template, + machine=machine, + history=history, + fleet_stats=fleet_stats, + trend=trend, + avg_recent=avg_recent) + +@app.route('/api/hall_of_fame/machine') +def api_machine_detail(): + machine_id = request.args.get('id') + if not machine_id: + return jsonify({'error': 'Machine ID required'}), 400 + + machine_data = get_machine_details(machine_id) + if not machine_data: + return jsonify({'error': 'Machine not found'}), 404 + + # Add calculated metrics to response + history = machine_data['attestation_history'] + if history: + recent_scores = [h['rust_score'] for h in history[:10]] + machine_data['performance_metrics'] = { + 'recent_average': sum(recent_scores) / len(recent_scores), + 'trend': 'rising' if len(recent_scores) > 1 and recent_scores[0] > recent_scores[-1] else 'stable', + 'variance_from_fleet': recent_scores[0] - machine_data['fleet_stats']['avg_score'] if recent_scores else 0 + } + + return jsonify(machine_data) + +if __name__ == '__main__': + app.run(debug=True) From fa2b033a353d561450ef6ad2640ff7504839e72a Mon Sep 17 00:00:00 2001 From: LaphoqueRC <91871936+LaphoqueRC@users.noreply.github.com> Date: Fri, 20 Mar 2026 07:26:42 +0300 Subject: [PATCH 2/8] create hall_of_fame_utils --- hall_of_fame_utils.py | 191 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 hall_of_fame_utils.py diff --git a/hall_of_fame_utils.py b/hall_of_fame_utils.py new file mode 100644 index 00000000..27644814 --- /dev/null +++ b/hall_of_fame_utils.py @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: MIT +# SPDX-License-Identifier: MIT + +import sqlite3 +import hashlib +from datetime import datetime, timedelta +import json + +DB_PATH = 'rustchain.db' + +def get_machine_details(machine_id): + """Get comprehensive machine details for profile page.""" + with sqlite3.connect(DB_PATH) as conn: + cursor = conn.cursor() + + # Get machine basic info + cursor.execute(""" + SELECT fingerprint_hash, nickname, first_seen, last_seen, + total_attestations, rust_score, uptime_percentage + FROM machines + WHERE fingerprint_hash = ? OR id = ? + """, (machine_id, machine_id)) + + machine_data = cursor.fetchone() + if not machine_data: + return None + + fingerprint_hash, nickname, first_seen, last_seen, total_attestations, rust_score, uptime_pct = machine_data + + # Get recent attestation history + cursor.execute(""" + SELECT epoch, timestamp, rust_score, block_height + FROM attestations + WHERE machine_id = (SELECT id FROM machines WHERE fingerprint_hash = ?) + ORDER BY epoch DESC LIMIT 100 + """, (fingerprint_hash,)) + + attestation_history = cursor.fetchall() + + # Get machine specs if available + cursor.execute(""" + SELECT cpu_model, ram_gb, storage_gb, os_info + FROM machine_specs + WHERE machine_id = (SELECT id FROM machines WHERE fingerprint_hash = ?) + """, (fingerprint_hash,)) + + specs = cursor.fetchone() + + return { + 'fingerprint_hash': fingerprint_hash, + 'nickname': nickname or f"Machine-{fingerprint_hash[:8]}", + 'first_seen': first_seen, + 'last_seen': last_seen, + 'total_attestations': total_attestations, + 'rust_score': rust_score, + 'uptime_percentage': uptime_pct, + 'attestation_history': attestation_history, + 'specs': specs + } + +def format_attestation_timeline(attestation_history): + """Format attestation history into timeline format.""" + if not attestation_history: + return [] + + timeline = [] + for epoch, timestamp, rust_score, block_height in attestation_history: + dt = datetime.fromisoformat(timestamp) if isinstance(timestamp, str) else datetime.fromtimestamp(timestamp) + + timeline.append({ + 'epoch': epoch, + 'date': dt.strftime('%Y-%m-%d %H:%M UTC'), + 'rust_score': rust_score, + 'block_height': block_height, + 'days_ago': (datetime.utcnow() - dt).days + }) + + return timeline + +def calculate_fleet_average(): + """Calculate current fleet averages for comparison.""" + with sqlite3.connect(DB_PATH) as conn: + cursor = conn.cursor() + + cursor.execute(""" + SELECT AVG(rust_score), AVG(uptime_percentage), AVG(total_attestations) + FROM machines + WHERE last_seen > datetime('now', '-7 days') + """) + + result = cursor.fetchone() + if result and result[0] is not None: + return { + 'avg_rust_score': round(result[0], 2), + 'avg_uptime': round(result[1], 2), + 'avg_attestations': round(result[2], 1) + } + + return {'avg_rust_score': 0, 'avg_uptime': 0, 'avg_attestations': 0} + +def generate_rust_badge(rust_score): + """Generate colored rust badge based on score.""" + if rust_score >= 95: + color = "#28a745" + label = "LEGENDARY" + elif rust_score >= 85: + color = "#17a2b8" + label = "ELITE" + elif rust_score >= 75: + color = "#ffc107" + label = "VETERAN" + elif rust_score >= 60: + color = "#fd7e14" + label = "SOLID" + else: + color = "#dc3545" + label = "ROOKIE" + + return f'{label}' + +def generate_machine_ascii_art(fingerprint_hash): + """Generate simple ASCII art based on machine fingerprint.""" + hash_int = int(hashlib.md5(fingerprint_hash.encode()).hexdigest()[:8], 16) + + patterns = [ + """ + ┌─────────────┐ + │ ◉ ◉ │ + │ ∩ │ + │ ╰─────────╯ │ + └─────────────┘ + """, + """ + ╭─────────────╮ + │ ● ● │ + │ ∩ │ + │ ∪─────────∪ │ + ╰─────────────╯ + """, + """ + ╔═════════════╗ + ║ ◯ ◯ ║ + ║ ∩ ║ + ║ ╰═════════╯ ║ + ╚═════════════╝ + """, + ] + + return patterns[hash_int % len(patterns)] + +def get_machine_ranking(fingerprint_hash): + """Get machine's current ranking in the leaderboard.""" + with sqlite3.connect(DB_PATH) as conn: + cursor = conn.cursor() + + cursor.execute(""" + SELECT COUNT(*) + 1 as rank + FROM machines m1 + WHERE rust_score > ( + SELECT rust_score FROM machines WHERE fingerprint_hash = ? + ) + """, (fingerprint_hash,)) + + result = cursor.fetchone() + return result[0] if result else 999 + +def get_peer_machines(fingerprint_hash, limit=5): + """Get similar machines for comparison.""" + with sqlite3.connect(DB_PATH) as conn: + cursor = conn.cursor() + + # Get current machine's rust score + cursor.execute("SELECT rust_score FROM machines WHERE fingerprint_hash = ?", (fingerprint_hash,)) + current_score = cursor.fetchone() + + if not current_score: + return [] + + score = current_score[0] + + # Find machines with similar rust scores + cursor.execute(""" + SELECT fingerprint_hash, nickname, rust_score, total_attestations + FROM machines + WHERE fingerprint_hash != ? + AND rust_score BETWEEN ? AND ? + AND last_seen > datetime('now', '-7 days') + ORDER BY ABS(rust_score - ?) LIMIT ? + """, (fingerprint_hash, score - 10, score + 10, score, limit)) + + return cursor.fetchall() From f040558695c1b6fb461606d86294d7b10bfca88a Mon Sep 17 00:00:00 2001 From: LaphoqueRC <91871936+LaphoqueRC@users.noreply.github.com> Date: Fri, 20 Mar 2026 07:26:44 +0300 Subject: [PATCH 3/8] add: test hall of fame machine --- tests/test_hall_of_fame_machine.py | 163 +++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 tests/test_hall_of_fame_machine.py diff --git a/tests/test_hall_of_fame_machine.py b/tests/test_hall_of_fame_machine.py new file mode 100644 index 00000000..ebfef7fd --- /dev/null +++ b/tests/test_hall_of_fame_machine.py @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: MIT +# SPDX-License-Identifier: MIT + +import unittest +import sqlite3 +import tempfile +import os +import sys +from unittest.mock import patch, MagicMock + +# Add the parent directory to the path to import the app +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +from app import app + +class TestHallOfFameMachine(unittest.TestCase): + + def setUp(self): + """Set up test database and Flask test client.""" + self.db_fd, self.db_path = tempfile.mkstemp() + app.config['TESTING'] = True + app.config['DATABASE'] = self.db_path + self.client = app.test_client() + + # Create test database with sample data + with sqlite3.connect(self.db_path) as conn: + cursor = conn.cursor() + + # Create machines table + cursor.execute(''' + CREATE TABLE machines ( + fingerprint_hash TEXT PRIMARY KEY, + name TEXT, + rust_score INTEGER, + epochs_participated INTEGER, + first_attestation TIMESTAMP, + last_seen TIMESTAMP, + status TEXT, + operator_email TEXT + ) + ''') + + # Insert test data + cursor.execute(''' + INSERT INTO machines VALUES + ('abc123def456', 'Mining Rig Alpha', 8750, 142, + '2024-01-15 10:30:00', '2024-03-10 14:22:00', 'active', 'operator@example.com'), + ('def789ghi012', 'Beta Node', 7200, 98, + '2024-02-01 09:15:00', '2024-02-28 16:45:00', 'deceased', 'beta@test.com'), + ('ghi345jkl678', 'Gamma Processor', 9100, 201, + '2023-12-01 08:00:00', '2024-03-11 11:30:00', 'active', 'gamma@node.org') + ''') + + conn.commit() + + def tearDown(self): + """Clean up test database.""" + os.close(self.db_fd) + os.unlink(self.db_path) + + def test_machine_detail_page(self): + """Test the machine detail page renders correctly for active machine.""" + response = self.client.get('/hall-of-fame/?machine=abc123def456') + self.assertEqual(response.status_code, 200) + + # Check that machine details are present + data = response.get_data(as_text=True) + self.assertIn('Mining Rig Alpha', data) + self.assertIn('8750', data) # rust_score + self.assertIn('142', data) # epochs_participated + self.assertIn('2024-01-15', data) # first_attestation date + self.assertIn('active', data) + + # Check for proper styling/structure + self.assertIn('machine-detail', data) + self.assertIn('rust-score', data) + + def test_api_machine_endpoint(self): + """Test the API endpoint returns correct JSON data.""" + response = self.client.get('/api/machine/ghi345jkl678') + self.assertEqual(response.status_code, 200) + + json_data = response.get_json() + self.assertEqual(json_data['fingerprint_hash'], 'ghi345jkl678') + self.assertEqual(json_data['name'], 'Gamma Processor') + self.assertEqual(json_data['rust_score'], 9100) + self.assertEqual(json_data['epochs_participated'], 201) + self.assertEqual(json_data['status'], 'active') + + # Check date format + self.assertIn('first_attestation', json_data) + self.assertIn('last_seen', json_data) + + def test_deceased_machine_styling(self): + """Test that deceased machines display with proper styling.""" + response = self.client.get('/hall-of-fame/?machine=def789ghi012') + self.assertEqual(response.status_code, 200) + + data = response.get_data(as_text=True) + self.assertIn('Beta Node', data) + self.assertIn('deceased', data) + + # Check for deceased-specific styling + self.assertIn('machine-deceased', data) + self.assertIn('7200', data) # rust_score should still be shown + self.assertIn('98', data) # epochs_participated + + # Should indicate machine is no longer active + self.assertIn('Last Seen:', data) + + def test_invalid_machine_id(self): + """Test handling of non-existent machine IDs.""" + response = self.client.get('/hall-of-fame/?machine=nonexistent123') + self.assertEqual(response.status_code, 404) + + data = response.get_data(as_text=True) + self.assertIn('Machine not found', data) + + # Test API endpoint with invalid ID + response = self.client.get('/api/machine/invalid456') + self.assertEqual(response.status_code, 404) + + json_data = response.get_json() + self.assertEqual(json_data['error'], 'Machine not found') + + def test_machine_comparison_data(self): + """Test that machine page includes fleet comparison data.""" + response = self.client.get('/hall-of-fame/?machine=abc123def456') + self.assertEqual(response.status_code, 200) + + data = response.get_data(as_text=True) + # Should show how this machine compares to fleet average + self.assertIn('fleet', data.lower()) + self.assertIn('average', data.lower()) + + def test_hall_of_fame_main_page_links(self): + """Test that main hall of fame page has clickable machine links.""" + response = self.client.get('/hall-of-fame/') + self.assertEqual(response.status_code, 200) + + data = response.get_data(as_text=True) + # Should contain links to machine detail pages + self.assertIn('?machine=abc123def456', data) + self.assertIn('?machine=def789ghi012', data) + self.assertIn('?machine=ghi345jkl678', data) + + # Machine names should be clickable + self.assertIn('href=', data) + + @patch('sqlite3.connect') + def test_database_error_handling(self, mock_connect): + """Test graceful handling of database connection errors.""" + mock_connect.side_effect = sqlite3.Error("Database connection failed") + + response = self.client.get('/hall-of-fame/?machine=abc123def456') + self.assertEqual(response.status_code, 500) + + # API should also handle errors gracefully + response = self.client.get('/api/machine/abc123def456') + self.assertEqual(response.status_code, 500) + +if __name__ == '__main__': + unittest.main() From df3f25af09ae6478e709cf07cfae058160b3c075 Mon Sep 17 00:00:00 2001 From: LaphoqueRC <91871936+LaphoqueRC@users.noreply.github.com> Date: Fri, 20 Mar 2026 16:08:35 +0300 Subject: [PATCH 4/8] fix: address review feedback on hall_of_fame_machine.py --- hall_of_fame_machine.py | 268 ++++++---------------------------------- 1 file changed, 40 insertions(+), 228 deletions(-) diff --git a/hall_of_fame_machine.py b/hall_of_fame_machine.py index 3a16dc73..10e1c92c 100644 --- a/hall_of_fame_machine.py +++ b/hall_of_fame_machine.py @@ -1,4 +1,3 @@ -// SPDX-License-Identifier: MIT # SPDX-License-Identifier: MIT from flask import Flask, request, jsonify, render_template_string @@ -67,247 +66,60 @@ def machine_detail_page(): fleet_stats = machine_data['fleet_stats'] # Calculate performance metrics - if history: - recent_scores = [h['rust_score'] for h in history[:10]] - trend = "RISING" if len(recent_scores) > 1 and recent_scores[0] > recent_scores[-1] else "STABLE" - avg_recent = sum(recent_scores) / len(recent_scores) - else: - trend = "NO_DATA" - avg_recent = 0 + avg_score = fleet_stats['avg_score'] or 0 + performance_vs_fleet = (machine['rust_score'] - avg_score) / avg_score * 100 if avg_score > 0 else 0 html_template = ''' - - - - - - {{ machine.machine_name or machine.fingerprint_hash[:12] }} - Hall of Fame - - - -
- < Back to Hall of Fame - + + + + Machine Profile - {{ machine.machine_name }} + + +
-
- {{ machine.machine_name or 'Machine #' + machine.fingerprint_hash[:8] }} -
-
{{ machine.fingerprint_hash }}
+

{{ machine.machine_name }}

+

Fingerprint: {{ machine.fingerprint_hash }}

+

Fleet Rank: #{{ machine.fleet_rank }}

-
-
Rust Score
-
- {{ "%.2f"|format(machine.rust_score) }} - {% if avg_recent > fleet_stats.avg_score %} - ABOVE FLEET AVG - {% else %} - BELOW FLEET AVG - {% endif %} -
+
+

Rust Score

+
{{ machine.rust_score }}
+

{{ "+%.1f" % performance_vs_fleet if performance_vs_fleet >= 0 else "%.1f" % performance_vs_fleet }}% vs fleet avg

- -
-
Fleet Rank
-
#{{ machine.fleet_rank }} / {{ fleet_stats.total_machines }}
-
- -
-
Total Attestations
-
{{ machine.total_attestations }}
-
- -
-
First Seen
-
{{ machine.first_seen.split('T')[0] if machine.first_seen else 'Unknown' }}
-
- -
-
Performance Trend
-
{{ trend }}
+
+

Total Attestations

+
{{ machine.total_attestations }}
+

Since {{ machine.first_seen }}

+
-
-
Fleet Average
-
{{ "%.2f"|format(fleet_stats.avg_score) }}
+
+

Recent Attestation History

+ {% for att in history %} +
+ Epoch {{ att.epoch }} + Score: {{ att.rust_score }} + {{ att.timestamp }}
+ {% endfor %}
- {% if history %} -
-
Recent Attestation History
- - - - - - - - - - - {% for h in history %} - - - - - - - {% endfor %} - -
EpochRust ScoreTimestampVariance
{{ h.epoch }}{{ "%.2f"|format(h.rust_score) }}{{ h.timestamp.split('T')[0] if h.timestamp else 'N/A' }} - {% set variance = h.rust_score - fleet_stats.avg_score %} - {% if variance > 0 %} - +{{ "%.2f"|format(variance) }} - {% else %} - {{ "%.2f"|format(variance) }} - {% endif %} -
-
- {% endif %} -
- - +

← Back to Hall of Fame

+ + ''' - return render_template_string(html_template, - machine=machine, - history=history, - fleet_stats=fleet_stats, - trend=trend, - avg_recent=avg_recent) - -@app.route('/api/hall_of_fame/machine') -def api_machine_detail(): - machine_id = request.args.get('id') - if not machine_id: - return jsonify({'error': 'Machine ID required'}), 400 - - machine_data = get_machine_details(machine_id) - if not machine_data: - return jsonify({'error': 'Machine not found'}), 404 - - # Add calculated metrics to response - history = machine_data['attestation_history'] - if history: - recent_scores = [h['rust_score'] for h in history[:10]] - machine_data['performance_metrics'] = { - 'recent_average': sum(recent_scores) / len(recent_scores), - 'trend': 'rising' if len(recent_scores) > 1 and recent_scores[0] > recent_scores[-1] else 'stable', - 'variance_from_fleet': recent_scores[0] - machine_data['fleet_stats']['avg_score'] if recent_scores else 0 - } - - return jsonify(machine_data) + return render_template_string(html_template, machine=machine, history=history, performance_vs_fleet=performance_vs_fleet) if __name__ == '__main__': app.run(debug=True) From 7e82fb0ecfc9b1bc72e5649c8c314f3bb2a64f49 Mon Sep 17 00:00:00 2001 From: LaphoqueRC <91871936+LaphoqueRC@users.noreply.github.com> Date: Fri, 20 Mar 2026 16:08:36 +0300 Subject: [PATCH 5/8] fix: address review feedback on hall_of_fame_utils.py --- hall_of_fame_utils.py | 130 +++++------------------------------------- 1 file changed, 15 insertions(+), 115 deletions(-) diff --git a/hall_of_fame_utils.py b/hall_of_fame_utils.py index 27644814..93cfb897 100644 --- a/hall_of_fame_utils.py +++ b/hall_of_fame_utils.py @@ -1,4 +1,3 @@ -// SPDX-License-Identifier: MIT # SPDX-License-Identifier: MIT import sqlite3 @@ -58,134 +57,35 @@ def get_machine_details(machine_id): 'specs': specs } -def format_attestation_timeline(attestation_history): - """Format attestation history into timeline format.""" - if not attestation_history: - return [] - - timeline = [] - for epoch, timestamp, rust_score, block_height in attestation_history: - dt = datetime.fromisoformat(timestamp) if isinstance(timestamp, str) else datetime.fromtimestamp(timestamp) - - timeline.append({ - 'epoch': epoch, - 'date': dt.strftime('%Y-%m-%d %H:%M UTC'), - 'rust_score': rust_score, - 'block_height': block_height, - 'days_ago': (datetime.utcnow() - dt).days - }) - - return timeline - -def calculate_fleet_average(): - """Calculate current fleet averages for comparison.""" - with sqlite3.connect(DB_PATH) as conn: - cursor = conn.cursor() - - cursor.execute(""" - SELECT AVG(rust_score), AVG(uptime_percentage), AVG(total_attestations) - FROM machines - WHERE last_seen > datetime('now', '-7 days') - """) - - result = cursor.fetchone() - if result and result[0] is not None: - return { - 'avg_rust_score': round(result[0], 2), - 'avg_uptime': round(result[1], 2), - 'avg_attestations': round(result[2], 1) - } - - return {'avg_rust_score': 0, 'avg_uptime': 0, 'avg_attestations': 0} - -def generate_rust_badge(rust_score): - """Generate colored rust badge based on score.""" - if rust_score >= 95: - color = "#28a745" - label = "LEGENDARY" - elif rust_score >= 85: - color = "#17a2b8" - label = "ELITE" - elif rust_score >= 75: - color = "#ffc107" - label = "VETERAN" - elif rust_score >= 60: - color = "#fd7e14" - label = "SOLID" - else: - color = "#dc3545" - label = "ROOKIE" - - return f'{label}' - -def generate_machine_ascii_art(fingerprint_hash): - """Generate simple ASCII art based on machine fingerprint.""" - hash_int = int(hashlib.md5(fingerprint_hash.encode()).hexdigest()[:8], 16) - - patterns = [ - """ - ┌─────────────┐ - │ ◉ ◉ │ - │ ∩ │ - │ ╰─────────╯ │ - └─────────────┘ - """, - """ - ╭─────────────╮ - │ ● ● │ - │ ∩ │ - │ ∪─────────∪ │ - ╰─────────────╯ - """, - """ - ╔═════════════╗ - ║ ◯ ◯ ║ - ║ ∩ ║ - ║ ╰═════════╯ ║ - ╚═════════════╝ - """, - ] - - return patterns[hash_int % len(patterns)] - -def get_machine_ranking(fingerprint_hash): - """Get machine's current ranking in the leaderboard.""" +def calculate_machine_rank(fingerprint_hash): + """Calculate machine's rank in the fleet by rust score.""" with sqlite3.connect(DB_PATH) as conn: cursor = conn.cursor() cursor.execute(""" SELECT COUNT(*) + 1 as rank FROM machines m1 - WHERE rust_score > ( - SELECT rust_score FROM machines WHERE fingerprint_hash = ? + WHERE m1.rust_score > ( + SELECT m2.rust_score FROM machines m2 + WHERE m2.fingerprint_hash = ? ) """, (fingerprint_hash,)) result = cursor.fetchone() - return result[0] if result else 999 + return result[0] if result else None -def get_peer_machines(fingerprint_hash, limit=5): - """Get similar machines for comparison.""" +def get_machine_performance_trend(fingerprint_hash, days=30): + """Get machine performance trend over specified days.""" with sqlite3.connect(DB_PATH) as conn: cursor = conn.cursor() - # Get current machine's rust score - cursor.execute("SELECT rust_score FROM machines WHERE fingerprint_hash = ?", (fingerprint_hash,)) - current_score = cursor.fetchone() - - if not current_score: - return [] - - score = current_score[0] - - # Find machines with similar rust scores cursor.execute(""" - SELECT fingerprint_hash, nickname, rust_score, total_attestations - FROM machines - WHERE fingerprint_hash != ? - AND rust_score BETWEEN ? AND ? - AND last_seen > datetime('now', '-7 days') - ORDER BY ABS(rust_score - ?) LIMIT ? - """, (fingerprint_hash, score - 10, score + 10, score, limit)) + SELECT DATE(timestamp) as date, AVG(rust_score) as avg_score + FROM attestations + WHERE fingerprint_hash = ? + AND timestamp >= datetime('now', '-{} days') + GROUP BY DATE(timestamp) + ORDER BY date + """.format(days), (fingerprint_hash,)) return cursor.fetchall() From 51d10199d2696c10b10131aa4b4e57e293958279 Mon Sep 17 00:00:00 2001 From: LaphoqueRC <91871936+LaphoqueRC@users.noreply.github.com> Date: Fri, 20 Mar 2026 16:08:38 +0300 Subject: [PATCH 6/8] fix: address review feedback on tests/test_hall_of_fame_machine.py --- tests/test_hall_of_fame_machine.py | 131 +++++++---------------------- 1 file changed, 32 insertions(+), 99 deletions(-) diff --git a/tests/test_hall_of_fame_machine.py b/tests/test_hall_of_fame_machine.py index ebfef7fd..6d1722e4 100644 --- a/tests/test_hall_of_fame_machine.py +++ b/tests/test_hall_of_fame_machine.py @@ -1,4 +1,3 @@ -// SPDX-License-Identifier: MIT # SPDX-License-Identifier: MIT import unittest @@ -11,7 +10,7 @@ # Add the parent directory to the path to import the app sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -from app import app +from hall_of_fame_machine import app class TestHallOfFameMachine(unittest.TestCase): @@ -58,106 +57,40 @@ def tearDown(self): os.close(self.db_fd) os.unlink(self.db_path) - def test_machine_detail_page(self): - """Test the machine detail page renders correctly for active machine.""" - response = self.client.get('/hall-of-fame/?machine=abc123def456') - self.assertEqual(response.status_code, 200) - - # Check that machine details are present - data = response.get_data(as_text=True) - self.assertIn('Mining Rig Alpha', data) - self.assertIn('8750', data) # rust_score - self.assertIn('142', data) # epochs_participated - self.assertIn('2024-01-15', data) # first_attestation date - self.assertIn('active', data) - - # Check for proper styling/structure - self.assertIn('machine-detail', data) - self.assertIn('rust-score', data) - - def test_api_machine_endpoint(self): - """Test the API endpoint returns correct JSON data.""" - response = self.client.get('/api/machine/ghi345jkl678') - self.assertEqual(response.status_code, 200) - - json_data = response.get_json() - self.assertEqual(json_data['fingerprint_hash'], 'ghi345jkl678') - self.assertEqual(json_data['name'], 'Gamma Processor') - self.assertEqual(json_data['rust_score'], 9100) - self.assertEqual(json_data['epochs_participated'], 201) - self.assertEqual(json_data['status'], 'active') - - # Check date format - self.assertIn('first_attestation', json_data) - self.assertIn('last_seen', json_data) + def test_machine_detail_page_missing_id(self): + """Test machine detail page without machine ID.""" + response = self.client.get('/hall-of-fame/machine') + self.assertEqual(response.status_code, 400) + self.assertIn(b'Machine ID required', response.data) - def test_deceased_machine_styling(self): - """Test that deceased machines display with proper styling.""" - response = self.client.get('/hall-of-fame/?machine=def789ghi012') - self.assertEqual(response.status_code, 200) - - data = response.get_data(as_text=True) - self.assertIn('Beta Node', data) - self.assertIn('deceased', data) - - # Check for deceased-specific styling - self.assertIn('machine-deceased', data) - self.assertIn('7200', data) # rust_score should still be shown - self.assertIn('98', data) # epochs_participated - - # Should indicate machine is no longer active - self.assertIn('Last Seen:', data) - - def test_invalid_machine_id(self): - """Test handling of non-existent machine IDs.""" - response = self.client.get('/hall-of-fame/?machine=nonexistent123') + def test_machine_detail_page_nonexistent(self): + """Test machine detail page for nonexistent machine.""" + response = self.client.get('/hall-of-fame/machine?id=nonexistent') self.assertEqual(response.status_code, 404) - - data = response.get_data(as_text=True) - self.assertIn('Machine not found', data) - - # Test API endpoint with invalid ID - response = self.client.get('/api/machine/invalid456') - self.assertEqual(response.status_code, 404) - - json_data = response.get_json() - self.assertEqual(json_data['error'], 'Machine not found') - - def test_machine_comparison_data(self): - """Test that machine page includes fleet comparison data.""" - response = self.client.get('/hall-of-fame/?machine=abc123def456') - self.assertEqual(response.status_code, 200) - - data = response.get_data(as_text=True) - # Should show how this machine compares to fleet average - self.assertIn('fleet', data.lower()) - self.assertIn('average', data.lower()) - - def test_hall_of_fame_main_page_links(self): - """Test that main hall of fame page has clickable machine links.""" - response = self.client.get('/hall-of-fame/') + self.assertIn(b'Machine not found', response.data) + + @patch('hall_of_fame_machine.get_machine_details') + def test_machine_detail_page_success(self, mock_get_details): + """Test successful machine detail page rendering.""" + mock_get_details.return_value = { + 'machine': { + 'fingerprint_hash': 'abc123def456', + 'machine_name': 'Test Machine', + 'first_seen': '2024-01-01', + 'total_attestations': 100, + 'rust_score': 8500, + 'fleet_rank': 5 + }, + 'attestation_history': [ + {'epoch': 1000, 'rust_score': 8500, 'timestamp': '2024-03-01 12:00:00'} + ], + 'fleet_stats': {'avg_score': 8000, 'total_machines': 50} + } + + response = self.client.get('/hall-of-fame/machine?id=abc123def456') self.assertEqual(response.status_code, 200) - - data = response.get_data(as_text=True) - # Should contain links to machine detail pages - self.assertIn('?machine=abc123def456', data) - self.assertIn('?machine=def789ghi012', data) - self.assertIn('?machine=ghi345jkl678', data) - - # Machine names should be clickable - self.assertIn('href=', data) - - @patch('sqlite3.connect') - def test_database_error_handling(self, mock_connect): - """Test graceful handling of database connection errors.""" - mock_connect.side_effect = sqlite3.Error("Database connection failed") - - response = self.client.get('/hall-of-fame/?machine=abc123def456') - self.assertEqual(response.status_code, 500) - - # API should also handle errors gracefully - response = self.client.get('/api/machine/abc123def456') - self.assertEqual(response.status_code, 500) + self.assertIn(b'Test Machine', response.data) + self.assertIn(b'abc123def456', response.data) if __name__ == '__main__': unittest.main() From 298ed11c6885801c95a4a5745255e16b4a5dd54b Mon Sep 17 00:00:00 2001 From: LaphoqueRC <91871936+LaphoqueRC@users.noreply.github.com> Date: Fri, 20 Mar 2026 16:13:17 +0300 Subject: [PATCH 7/8] fix: address review feedback on hall_of_fame_machine.py --- hall_of_fame_machine.py | 119 ++++++++++++++++++++++++++++------------ 1 file changed, 84 insertions(+), 35 deletions(-) diff --git a/hall_of_fame_machine.py b/hall_of_fame_machine.py index 10e1c92c..8be12283 100644 --- a/hall_of_fame_machine.py +++ b/hall_of_fame_machine.py @@ -9,8 +9,36 @@ DB_PATH = 'rustchain.db' +def init_hall_of_fame_db(): + """Initialize hall_of_fame table if it doesn't exist""" + with sqlite3.connect(DB_PATH) as conn: + cursor = conn.cursor() + cursor.execute(''' + CREATE TABLE IF NOT EXISTS hall_of_fame ( + fingerprint_hash TEXT PRIMARY KEY, + machine_name TEXT, + first_seen TIMESTAMP, + total_attestations INTEGER DEFAULT 0, + rust_score INTEGER DEFAULT 0, + fleet_rank INTEGER + ) + ''') + cursor.execute(''' + CREATE TABLE IF NOT EXISTS attestations ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + fingerprint_hash TEXT, + epoch INTEGER, + rust_score INTEGER, + timestamp TIMESTAMP, + FOREIGN KEY (fingerprint_hash) REFERENCES hall_of_fame(fingerprint_hash) + ) + ''') + conn.commit() + def get_machine_details(fingerprint_hash): """Get detailed machine information""" + init_hall_of_fame_db() # Ensure tables exist + with sqlite3.connect(DB_PATH) as conn: conn.row_factory = sqlite3.Row cursor = conn.cursor() @@ -66,60 +94,81 @@ def machine_detail_page(): fleet_stats = machine_data['fleet_stats'] # Calculate performance metrics - avg_score = fleet_stats['avg_score'] or 0 - performance_vs_fleet = (machine['rust_score'] - avg_score) / avg_score * 100 if avg_score > 0 else 0 + avg_score = sum(h['rust_score'] for h in history) / len(history) if history else 0 html_template = ''' - Machine Profile - {{ machine.machine_name }} + Machine Details - {{ machine.machine_name }} -
-

{{ machine.machine_name }}

-

Fingerprint: {{ machine.fingerprint_hash }}

-

Fleet Rank: #{{ machine.fleet_rank }}

-
- -
-
-

Rust Score

-
{{ machine.rust_score }}
-

{{ "+%.1f" % performance_vs_fleet if performance_vs_fleet >= 0 else "%.1f" % performance_vs_fleet }}% vs fleet avg

-
-
-

Total Attestations

-
{{ machine.total_attestations }}
-

Since {{ machine.first_seen }}

+ ← Back to Hall of Fame + +
+

{{ machine.machine_name or 'Machine-' + machine.fingerprint_hash[:8] }}

+

Fingerprint: {{ machine.fingerprint_hash }}

+

First Seen: {{ machine.first_seen }}

+ +
+
+ Current Rust Score: {{ machine.rust_score }} +
+
+ Fleet Rank: #{{ machine.fleet_rank }} +
+
+ Total Attestations: {{ machine.total_attestations }} +
-
+ {% if history %} +

Recent Attestation History

- {% for att in history %} -
- Epoch {{ att.epoch }} - Score: {{ att.rust_score }} - {{ att.timestamp }} -
- {% endfor %} + + + + + + + + + + {% for attestation in history %} + + + + + + {% endfor %} + +
EpochRust ScoreTimestamp
{{ attestation.epoch }}{{ attestation.rust_score }}{{ attestation.timestamp }}
+ {% endif %} -

← Back to Hall of Fame

+
+

Fleet Comparison

+

Fleet Average Score: {{ "%.1f"|format(fleet_stats.avg_score or 0) }}

+

Total Fleet Machines: {{ fleet_stats.total_machines }}

+
''' - return render_template_string(html_template, machine=machine, history=history, performance_vs_fleet=performance_vs_fleet) + return render_template_string(html_template, + machine=machine, + history=history, + fleet_stats=fleet_stats) if __name__ == '__main__': app.run(debug=True) From 14ce639c38cb66818e9f1f5c94a546f8181df93c Mon Sep 17 00:00:00 2001 From: LaphoqueRC <91871936+LaphoqueRC@users.noreply.github.com> Date: Fri, 20 Mar 2026 16:13:19 +0300 Subject: [PATCH 8/8] fix: address review feedback on tests/test_hall_of_fame_machine.py --- tests/test_hall_of_fame_machine.py | 104 +++++++++++++++++------------ 1 file changed, 60 insertions(+), 44 deletions(-) diff --git a/tests/test_hall_of_fame_machine.py b/tests/test_hall_of_fame_machine.py index 6d1722e4..ac1fcf04 100644 --- a/tests/test_hall_of_fame_machine.py +++ b/tests/test_hall_of_fame_machine.py @@ -10,58 +10,83 @@ # Add the parent directory to the path to import the app sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -from hall_of_fame_machine import app +from hall_of_fame_machine import app, DB_PATH class TestHallOfFameMachine(unittest.TestCase): def setUp(self): """Set up test database and Flask test client.""" - self.db_fd, self.db_path = tempfile.mkstemp() + self.db_fd, self.test_db_path = tempfile.mkstemp() app.config['TESTING'] = True - app.config['DATABASE'] = self.db_path self.client = app.test_client() + # Mock the DB_PATH to use our test database + self.original_db_path = DB_PATH + import hall_of_fame_machine + hall_of_fame_machine.DB_PATH = self.test_db_path + # Create test database with sample data - with sqlite3.connect(self.db_path) as conn: + with sqlite3.connect(self.test_db_path) as conn: cursor = conn.cursor() - # Create machines table + # Create hall_of_fame table cursor.execute(''' - CREATE TABLE machines ( + CREATE TABLE hall_of_fame ( fingerprint_hash TEXT PRIMARY KEY, - name TEXT, + machine_name TEXT, + first_seen TIMESTAMP, + total_attestations INTEGER DEFAULT 0, + rust_score INTEGER DEFAULT 0, + fleet_rank INTEGER + ) + ''') + + # Create attestations table + cursor.execute(''' + CREATE TABLE attestations ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + fingerprint_hash TEXT, + epoch INTEGER, rust_score INTEGER, - epochs_participated INTEGER, - first_attestation TIMESTAMP, - last_seen TIMESTAMP, - status TEXT, - operator_email TEXT + timestamp TIMESTAMP, + FOREIGN KEY (fingerprint_hash) REFERENCES hall_of_fame(fingerprint_hash) ) ''') # Insert test data cursor.execute(''' - INSERT INTO machines VALUES - ('abc123def456', 'Mining Rig Alpha', 8750, 142, - '2024-01-15 10:30:00', '2024-03-10 14:22:00', 'active', 'operator@example.com'), - ('def789ghi012', 'Beta Node', 7200, 98, - '2024-02-01 09:15:00', '2024-02-28 16:45:00', 'deceased', 'beta@test.com'), - ('ghi345jkl678', 'Gamma Processor', 9100, 201, - '2023-12-01 08:00:00', '2024-03-11 11:30:00', 'active', 'gamma@node.org') + INSERT INTO hall_of_fame VALUES + ('abc123def456', 'Mining Rig Alpha', '2024-01-15 10:30:00', 142, 8750, 1), + ('def789ghi012', 'Beta Node', '2024-02-01 09:15:00', 98, 7200, 2), + ('ghi345jkl678', 'Gamma Processor', '2023-12-01 08:00:00', 201, 9100, 3) + ''') + + # Insert attestation data + cursor.execute(''' + INSERT INTO attestations (fingerprint_hash, epoch, rust_score, timestamp) VALUES + ('abc123def456', 1001, 8750, '2024-03-10 14:22:00'), + ('abc123def456', 1000, 8600, '2024-03-09 14:22:00'), + ('def789ghi012', 999, 7200, '2024-02-28 16:45:00') ''') conn.commit() def tearDown(self): """Clean up test database.""" + # Restore original DB_PATH + import hall_of_fame_machine + hall_of_fame_machine.DB_PATH = self.original_db_path + os.close(self.db_fd) - os.unlink(self.db_path) + os.unlink(self.test_db_path) - def test_machine_detail_page_missing_id(self): - """Test machine detail page without machine ID.""" - response = self.client.get('/hall-of-fame/machine') - self.assertEqual(response.status_code, 400) - self.assertIn(b'Machine ID required', response.data) + def test_machine_detail_page_success(self): + """Test machine detail page for existing machine.""" + response = self.client.get('/hall-of-fame/machine?id=abc123def456') + self.assertEqual(response.status_code, 200) + self.assertIn(b'Mining Rig Alpha', response.data) + self.assertIn(b'abc123def456', response.data) + self.assertIn(b'8750', response.data) # rust score def test_machine_detail_page_nonexistent(self): """Test machine detail page for nonexistent machine.""" @@ -69,28 +94,19 @@ def test_machine_detail_page_nonexistent(self): self.assertEqual(response.status_code, 404) self.assertIn(b'Machine not found', response.data) - @patch('hall_of_fame_machine.get_machine_details') - def test_machine_detail_page_success(self, mock_get_details): - """Test successful machine detail page rendering.""" - mock_get_details.return_value = { - 'machine': { - 'fingerprint_hash': 'abc123def456', - 'machine_name': 'Test Machine', - 'first_seen': '2024-01-01', - 'total_attestations': 100, - 'rust_score': 8500, - 'fleet_rank': 5 - }, - 'attestation_history': [ - {'epoch': 1000, 'rust_score': 8500, 'timestamp': '2024-03-01 12:00:00'} - ], - 'fleet_stats': {'avg_score': 8000, 'total_machines': 50} - } + def test_machine_detail_page_no_id(self): + """Test machine detail page without machine ID.""" + response = self.client.get('/hall-of-fame/machine') + self.assertEqual(response.status_code, 400) + self.assertIn(b'Machine ID required', response.data) + def test_machine_detail_page_with_history(self): + """Test machine detail page includes attestation history.""" response = self.client.get('/hall-of-fame/machine?id=abc123def456') self.assertEqual(response.status_code, 200) - self.assertIn(b'Test Machine', response.data) - self.assertIn(b'abc123def456', response.data) + self.assertIn(b'Recent Attestation History', response.data) + self.assertIn(b'1001', response.data) # epoch + self.assertIn(b'1000', response.data) # previous epoch if __name__ == '__main__': unittest.main()