second commit
parent
8442713311
commit
bc19dd67e9
|
@ -0,0 +1,41 @@
|
||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
from flask import Flask, request, render_template, redirect
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
# Global storage for the current challenge
|
||||||
|
current_challenge = {}
|
||||||
|
|
||||||
|
# Redirect root URL to get-challenge
|
||||||
|
@app.route('/', methods=['GET'])
|
||||||
|
def index():
|
||||||
|
return redirect('/get-challenge') # Redirect to the challenge page
|
||||||
|
|
||||||
|
# Generate a nonce and difficulty for the client
|
||||||
|
@app.route('/get-challenge', methods=['GET'])
|
||||||
|
def get_challenge():
|
||||||
|
global current_challenge
|
||||||
|
nonce = os.urandom(16).hex() # Generate a random 16-byte nonce
|
||||||
|
difficulty = 4 # Set the difficulty (number of leading zeros)
|
||||||
|
current_challenge = {'nonce': nonce, 'difficulty': difficulty}
|
||||||
|
return render_template('challenge.html', nonce=nonce, difficulty=difficulty)
|
||||||
|
|
||||||
|
# Verify the solution provided by the client
|
||||||
|
@app.route('/verify', methods=['POST'])
|
||||||
|
def verify_solution():
|
||||||
|
solution = request.form['solution']
|
||||||
|
nonce = current_challenge['nonce']
|
||||||
|
difficulty = current_challenge['difficulty']
|
||||||
|
|
||||||
|
# Recompute the hash with the client's solution
|
||||||
|
hash_result = hashlib.sha256((nonce + solution).encode()).hexdigest()
|
||||||
|
|
||||||
|
# Check if the hash has the required number of leading zeros
|
||||||
|
if hash_result.startswith('0' * difficulty):
|
||||||
|
return render_template('result.html', status="Success! Solution is correct.")
|
||||||
|
else:
|
||||||
|
return render_template('result.html', status="Failed. Incorrect solution.")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(host='0.0.0.0', port=6969)
|
|
@ -0,0 +1,11 @@
|
||||||
|
* Serving Flask app 'app'
|
||||||
|
* Debug mode: off
|
||||||
|
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
|
||||||
|
* Running on all addresses (0.0.0.0)
|
||||||
|
* Running on http://127.0.0.1:6969
|
||||||
|
* Running on http://87.120.112.23:6969
|
||||||
|
Press CTRL+C to quit
|
||||||
|
172.58.127.76 - - [22/Oct/2024 15:40:16] "GET / HTTP/1.1" 200 -
|
||||||
|
172.58.127.76 - - [22/Oct/2024 15:40:16] "GET /static/main.js HTTP/1.1" 200 -
|
||||||
|
172.58.127.76 - - [22/Oct/2024 15:40:17] "GET /favicon.ico HTTP/1.1" 404 -
|
||||||
|
172.58.127.76 - - [22/Oct/2024 15:40:18] "GET /get-challenge HTTP/1.1" 200 -
|
|
@ -0,0 +1,16 @@
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
# Get user inputs for nonce and difficulty
|
||||||
|
nonce = input("Enter the nonce: ")
|
||||||
|
difficulty = int(input("Enter the difficulty (number of leading zeros): "))
|
||||||
|
|
||||||
|
def sha256(message):
|
||||||
|
return hashlib.sha256(message.encode()).hexdigest()
|
||||||
|
|
||||||
|
solution = 0
|
||||||
|
while True:
|
||||||
|
hash_result = sha256(nonce + str(solution))
|
||||||
|
if hash_result.startswith('0' * difficulty):
|
||||||
|
print("Solution found:", solution)
|
||||||
|
break
|
||||||
|
solution += 1
|
|
@ -0,0 +1,47 @@
|
||||||
|
async function sha256(message) {
|
||||||
|
const msgBuffer = new TextEncoder().encode(message);
|
||||||
|
const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
|
||||||
|
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
||||||
|
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
|
||||||
|
return hashHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function startPoW() {
|
||||||
|
document.getElementById('status').innerText = "Starting PoW...";
|
||||||
|
|
||||||
|
// Fetch challenge from the server
|
||||||
|
const response = await fetch('/get-challenge');
|
||||||
|
const challenge = await response.json();
|
||||||
|
const { nonce, difficulty } = challenge;
|
||||||
|
|
||||||
|
let solution = 0;
|
||||||
|
let hash = '';
|
||||||
|
|
||||||
|
// Brute-force to find a solution
|
||||||
|
while (true) {
|
||||||
|
hash = await sha256(nonce + solution);
|
||||||
|
if (hash.startsWith('0'.repeat(difficulty))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
solution++;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('status').innerText = `Solution found: ${solution} (Hash: ${hash})`;
|
||||||
|
|
||||||
|
// Send the solution back to the server for verification
|
||||||
|
const verifyResponse = await fetch('/verify', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ nonce, solution: solution.toString(), difficulty })
|
||||||
|
});
|
||||||
|
|
||||||
|
if (verifyResponse.status === 200) {
|
||||||
|
document.getElementById('status').innerText += " - Verified!";
|
||||||
|
} else {
|
||||||
|
document.getElementById('status').innerText += " - Verification failed!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('start-pow').addEventListener('click', startPoW);
|
|
@ -0,0 +1,77 @@
|
||||||
|
body {
|
||||||
|
font-family: 'Courier New', Courier, monospace;
|
||||||
|
background-color: #1e1e1e; /* Dark background for a circuit board feel */
|
||||||
|
color: #c9c9c9; /* Light text color */
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
background: #2e2e2e; /* Darker box background */
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 20px;
|
||||||
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
|
||||||
|
max-width: 600px; /* Limit width for better appearance */
|
||||||
|
margin: auto; /* Center the container */
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2 {
|
||||||
|
color: #4CAF50; /* Green text for headers */
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
border-bottom: 2px solid #4CAF50; /* Underline for h1 */
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"] {
|
||||||
|
padding: 10px;
|
||||||
|
margin-top: 10px;
|
||||||
|
width: 100%; /* Full width for input */
|
||||||
|
border: 1px solid #4CAF50; /* Green border */
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #333; /* Darker input field */
|
||||||
|
color: #c9c9c9; /* Light text color */
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 10px 15px;
|
||||||
|
background-color: #4CAF50; /* Green button */
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s; /* Smooth hover transition */
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background-color: #45a049; /* Darker green on hover */
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 20px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #4CAF50; /* Green for links */
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline; /* Underline links on hover */
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-box {
|
||||||
|
background-color: #2e2e2e; /* Dark background for code boxes */
|
||||||
|
border: 1px solid #4CAF50; /* Green border for code boxes */
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 10px;
|
||||||
|
overflow-x: auto; /* Allow horizontal scrolling */
|
||||||
|
font-family: 'Courier New', Courier, monospace; /* Monospace font for code */
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Proof of Work Challenge</title>
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Proof of Work Challenge</h1>
|
||||||
|
<p><strong>Nonce:</strong> {{ nonce }}</p>
|
||||||
|
<p><strong>Difficulty:</strong> {{ difficulty }}</p>
|
||||||
|
|
||||||
|
<h2>Instructions</h2>
|
||||||
|
<p>To solve the Proof of Work challenge, run the following Python script locally with the provided nonce:</p>
|
||||||
|
<div class="code-box">
|
||||||
|
<pre>
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
nonce = "{{ nonce }}"
|
||||||
|
difficulty = {{ difficulty }}
|
||||||
|
|
||||||
|
def sha256(message):
|
||||||
|
return hashlib.sha256(message.encode()).hexdigest()
|
||||||
|
|
||||||
|
solution = 0
|
||||||
|
while True:
|
||||||
|
hash_result = sha256(nonce + str(solution))
|
||||||
|
if hash_result.startswith('0' * difficulty):
|
||||||
|
print("Solution found:", solution)
|
||||||
|
break
|
||||||
|
solution += 1
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>Once you've found the solution, enter it below:</p>
|
||||||
|
|
||||||
|
<form action="/verify" method="post">
|
||||||
|
<label for="solution">Solution:</label>
|
||||||
|
<input type="text" id="solution" name="solution" required>
|
||||||
|
<button type="submit">Verify</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,17 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Verification Result</title>
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Verification Result</h1>
|
||||||
|
<p>{{ status }}</p>
|
||||||
|
|
||||||
|
<a href="/get-challenge">Try Another Challenge</a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue