mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-08 22:28:12 -05:00
script/research/blockchain-explorer/site: rest pages added, cleaned up code, licencing added
This commit is contained in:
@@ -18,7 +18,8 @@ First we start a `darkfid` localnet:
|
||||
|
||||
It is advised to shutdown the `minerd` daemon after couple of blocks, to not waste resources.
|
||||
|
||||
Now we start a `blockchain-explorer` daemon:
|
||||
Update the `blockchain-explorer` configuration to the localnet `darkfid` JSON-RPC endpoint
|
||||
and start a the daemon:
|
||||
|
||||
```
|
||||
% cd script/research/blockchain-explorer
|
||||
|
||||
@@ -1,17 +1,59 @@
|
||||
from flask import Flask, render_template
|
||||
# This file is part of DarkFi (https://dark.fi)
|
||||
#
|
||||
# Copyright (C) 2020-2024 Dyne.org foundation
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import asyncio
|
||||
from flask import Flask, request, render_template
|
||||
|
||||
import rpc
|
||||
|
||||
# DarkFi blockchain-explorer daemon JSON-RPC configuration
|
||||
# TODO: make this configurable
|
||||
URL = "127.0.0.1"
|
||||
PORT = 14567
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/')
|
||||
async def index():
|
||||
blocks = await rpc.get_last_n_blocks(10, URL, PORT)
|
||||
stats = await rpc.get_basic_statistics(URL, PORT)
|
||||
blocks = await rpc.get_last_n_blocks("10")
|
||||
stats = await rpc.get_basic_statistics()
|
||||
return render_template('index.html', blocks=blocks, stats=stats)
|
||||
|
||||
@app.route('/search', methods=['GET', 'POST'])
|
||||
async def search():
|
||||
search_hash = request.args.get('search_hash', '')
|
||||
try:
|
||||
block = await rpc.get_block(search_hash)
|
||||
transactions = await rpc.get_block_transactions(search_hash)
|
||||
return render_template('block.html', block=block, transactions=transactions)
|
||||
except Exception:
|
||||
transaction = await rpc.get_transaction(search_hash)
|
||||
return render_template('transaction.html', transaction=transaction)
|
||||
|
||||
@app.route('/block/<header_hash>')
|
||||
async def block(header_hash):
|
||||
block = await rpc.get_block(header_hash)
|
||||
transactions = await rpc.get_block_transactions(header_hash)
|
||||
return render_template('block.html', block=block, transactions=transactions)
|
||||
|
||||
@app.route('/transaction/<transaction_hash>')
|
||||
async def transaction(transaction_hash):
|
||||
transaction = await rpc.get_transaction(transaction_hash)
|
||||
return render_template('transaction.html', transaction=transaction)
|
||||
|
||||
@app.errorhandler(404)
|
||||
def page_not_found(e):
|
||||
return render_template('404.html'), 404
|
||||
|
||||
@app.errorhandler(500)
|
||||
def page_not_found(e):
|
||||
return render_template('500.html'), 500
|
||||
|
||||
@@ -1,8 +1,28 @@
|
||||
# This file is part of DarkFi (https://dark.fi)
|
||||
#
|
||||
# Copyright (C) 2020-2024 Dyne.org foundation
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import asyncio, json, random
|
||||
from flask import abort
|
||||
|
||||
# TODO have a single channel for the whole app
|
||||
# Class representing the channel with the JSON-RPC server.
|
||||
# DarkFi blockchain-explorer daemon JSON-RPC configuration
|
||||
URL = "127.0.0.1"
|
||||
PORT = 14567
|
||||
|
||||
# Class representing the channel with the JSON-RPC server
|
||||
class Channel:
|
||||
def __init__(self, reader, writer):
|
||||
self.reader = reader
|
||||
@@ -40,10 +60,9 @@ async def create_channel(server_name, port):
|
||||
channel = Channel(reader, writer)
|
||||
return channel
|
||||
|
||||
|
||||
# Execute a request towards the JSON-RPC server
|
||||
async def query(method, params, server_name, port):
|
||||
channel = await create_channel(server_name, port)
|
||||
async def query(method, params):
|
||||
channel = await create_channel(URL, PORT)
|
||||
request = {
|
||||
"id": random.randint(0, 2**32),
|
||||
"method": method,
|
||||
@@ -55,21 +74,34 @@ async def query(method, params, server_name, port):
|
||||
response = await channel.receive()
|
||||
# Closed connect returns None
|
||||
if response is None:
|
||||
print("error: connection with server was closed", file=sys.stderr)
|
||||
print("error: connection with server was closed")
|
||||
abort(500)
|
||||
|
||||
# Erroneous query is handled with not found
|
||||
if "error" in response:
|
||||
error = response["error"]
|
||||
errcode, errmsg = error["code"], error["message"]
|
||||
print(f"error: {errcode} - {errmsg}", file=sys.stderr)
|
||||
abort(500)
|
||||
print(f"error: {errcode} - {errmsg}")
|
||||
abort(404)
|
||||
|
||||
return response["result"]
|
||||
|
||||
# Retrieve last n blocks from blockchain-explorer daemon
|
||||
async def get_last_n_blocks(n, server_name, port):
|
||||
return await query("blocks.get_last_n_blocks", [str(n)], server_name, int(port))
|
||||
async def get_last_n_blocks(n: str):
|
||||
return await query("blocks.get_last_n_blocks", [n])
|
||||
|
||||
# Retrieve basic statistics from blockchain-explorer daemon
|
||||
async def get_basic_statistics(server_name, port):
|
||||
return await query("statistics.get_basic_statistics", [], server_name, int(port))
|
||||
async def get_basic_statistics():
|
||||
return await query("statistics.get_basic_statistics", [])
|
||||
|
||||
# Retrieve the block information of given header hash from blockchain-explorer daemon
|
||||
async def get_block(header_hash: str):
|
||||
return await query("blocks.get_block_by_hash", [header_hash])
|
||||
|
||||
# Retrieve the transactions of given block header hash from blockchain-explorer daemon
|
||||
async def get_block_transactions(header_hash: str):
|
||||
return await query("transactions.get_transactions_by_header_hash", [header_hash])
|
||||
|
||||
# Retrieve the transaction information of given hash from blockchain-explorer daemon
|
||||
async def get_transaction(transaction_hash: str):
|
||||
return await query("transactions.get_transaction_by_hash", [transaction_hash])
|
||||
|
||||
BIN
script/research/blockchain-explorer/site/static/img/darkfi05.jpg
Normal file
BIN
script/research/blockchain-explorer/site/static/img/darkfi05.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 222 KiB |
BIN
script/research/blockchain-explorer/site/static/img/darkfi25.jpg
Normal file
BIN
script/research/blockchain-explorer/site/static/img/darkfi25.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 317 KiB |
@@ -828,3 +828,17 @@ h5 a:hover{
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Container holding an image with text on top */
|
||||
.background-container {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Top centered text inside a background-container */
|
||||
.top-centered {
|
||||
position: absolute;
|
||||
top: 25%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -25%);
|
||||
}
|
||||
|
||||
35
script/research/blockchain-explorer/site/templates/404.html
Normal file
35
script/research/blockchain-explorer/site/templates/404.html
Normal file
@@ -0,0 +1,35 @@
|
||||
<!--
|
||||
This file is part of DarkFi (https://dark.fi)
|
||||
|
||||
Copyright (C) 2020-2024 Dyne.org foundation
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Not found!{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="background-container">
|
||||
<img src="../static/img/darkfi25.jpg" style="width:100%;">
|
||||
<div class="top-centered">
|
||||
<h1 class="display-4 text-white border-l3" style="font-family:'Weissrundgotisch';line-height:.9em;">
|
||||
Is this what you are looking for?
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
35
script/research/blockchain-explorer/site/templates/500.html
Normal file
35
script/research/blockchain-explorer/site/templates/500.html
Normal file
@@ -0,0 +1,35 @@
|
||||
<!--
|
||||
This file is part of DarkFi (https://dark.fi)
|
||||
|
||||
Copyright (C) 2020-2024 Dyne.org foundation
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Not found!{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="background-container">
|
||||
<img src="../static/img/darkfi05.jpg" style="width:100%;">
|
||||
<div class="top-centered">
|
||||
<h1 class="display-4 text-white border-l3" style="font-family:'Weissrundgotisch';line-height:.9em;">
|
||||
Reality fractured beyond repair!
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
<!--
|
||||
This file is part of DarkFi (https://dark.fi)
|
||||
|
||||
Copyright (C) 2020-2024 Dyne.org foundation
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<!--
|
||||
This file is part of DarkFi (https://dark.fi)
|
||||
|
||||
Copyright (C) 2020-2024 Dyne.org foundation
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Block {{ block[0] }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="container-fluid pl-5 pb-5 pr-5 title-block" style="margin-top:90px;">
|
||||
<h1 class="display-4 text-white border-l3" style="font-family:'Weissrundgotisch';line-height:.9em;">Block {{ block[0] }}</h1>
|
||||
</div>
|
||||
|
||||
<div class="row m-0 border-secondary border-top">
|
||||
<div class="text-white mb-0 border-bottom border-secondary lead-text" style="width:100%;">
|
||||
<ul>
|
||||
<li>Version: {{ block[1] }}</li>
|
||||
<li>Previous: <a href="../block/{{ block[2] }}">{{ block[2] }}</a></li>
|
||||
<li>Height: {{ block[3] }}</li>
|
||||
<li>Timestamp: {{ block[4] }}</li>
|
||||
<li>Nonce: {{ block[5] }}</li>
|
||||
<li>Root: {{ block[6] }}</li>
|
||||
<li>Signature: {{ block[7] }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row m-0 border-secondary border-top">
|
||||
<div class="text-white mb-0 border-bottom border-secondary lead-text" style="width:100%;">
|
||||
<h2 class="display-8 text-white border-l3" style="font-family:'Weissrundgotisch';line-height:.9em;">Transactions</h2>
|
||||
<ul>
|
||||
{% for transaction in transactions %}
|
||||
<li><a href="../transaction/{{ transaction[0] }}">{{ transaction[0] }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,38 +1,67 @@
|
||||
<!--
|
||||
This file is part of DarkFi (https://dark.fi)
|
||||
|
||||
Copyright (C) 2020-2024 Dyne.org foundation
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Explorer{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid pl-5 pb-5 pr-5 title-block" style="margin-top:90px;">
|
||||
<h1 class="display-4 text-white border-l3" style="font-family:'Weissrundgotisch';line-height:.9em;">Explorer</h1>
|
||||
</div>
|
||||
|
||||
<div class="row m-0 border-secondary border-top"/>
|
||||
<div class="col-md-7 text-white mb-0 border-right border-bottom border-secondary lead-text">
|
||||
<h2 class="display-8 text-white border-l3" style="font-family:'Weissrundgotisch';line-height:.9em;">Latest Blocks</h2>
|
||||
<table>
|
||||
<tr style="text-align: center;">
|
||||
<th>Height</th>
|
||||
<th>Hash</th>
|
||||
<th>timestamp</th>
|
||||
</tr>
|
||||
{% for block in blocks %}
|
||||
<tr>
|
||||
<td>{{ block[3] }}</td>
|
||||
<td>{{ block[0] }}</td>
|
||||
<td>{{ block[4] }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<div class="container-fluid pl-5 pb-5 pr-5 title-block" style="margin-top:90px;">
|
||||
<h1 class="display-4 text-white border-l3" style="font-family:'Weissrundgotisch';line-height:.9em;">Explore</h1>
|
||||
<div class="search-container">
|
||||
<form action="/search">
|
||||
<input type="text" placeholder="Search for a block or transaction.." name="search_hash">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5 text-white m-0 border-secondary border-bottom lead-text">
|
||||
<h2 class="display-8 text-white border-l3" style="font-family:'Weissrundgotisch';line-height:.9em;">Statistics</h2>
|
||||
<ul>
|
||||
<li>Height: {{ stats[0] }}</li>
|
||||
<li>Epoch: {{ stats[1] }}</li>
|
||||
<li>Last block: {{ stats[2] }}</li>
|
||||
<li>Total blocks: {{ stats[3] }}</li>
|
||||
<li>Total transactions: {{ stats[4] }}</li>
|
||||
</ul>
|
||||
|
||||
<div class="row m-0 border-secondary border-top">
|
||||
<div class="text-white mb-0 border-bottom border-secondary lead-text" style="width:100%;">
|
||||
<h2 class="display-8 text-white border-l3" style="font-family:'Weissrundgotisch';line-height:.9em;">Latest Blocks</h2>
|
||||
<table style="width:100%;">
|
||||
<tr>
|
||||
<th>Height</th>
|
||||
<th>Hash</th>
|
||||
<th>Timestamp</th>
|
||||
</tr>
|
||||
{% for block in blocks %}
|
||||
<tr>
|
||||
<td>{{ block[3] }}</td>
|
||||
<td><a href="block/{{ block[0] }}">{{ block[0] }}</a></td>
|
||||
<td>{{ block[4] }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row m-0 border-secondary border-top">
|
||||
<div class="text-white mb-0 border-bottom border-secondary lead-text" style="width:100%;">
|
||||
<h2 class="display-8 text-white border-l3" style="font-family:'Weissrundgotisch';line-height:.9em;">Statistics</h2>
|
||||
<ul>
|
||||
<li>Height: {{ stats[0] }}</li>
|
||||
<li>Epoch: {{ stats[1] }}</li>
|
||||
<li>Last block: <a href="block/{{ stats[2] }}">{{ stats[2] }}</a></li>
|
||||
<li>Total blocks: {{ stats[3] }}</li>
|
||||
<li>Total transactions: {{ stats[4] }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
<!--
|
||||
This file is part of DarkFi (https://dark.fi)
|
||||
|
||||
Copyright (C) 2020-2024 Dyne.org foundation
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Transaction {{ transaction[0] }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="container-fluid pl-5 pb-5 pr-5 title-block" style="margin-top:90px;">
|
||||
<h1 class="display-4 text-white border-l3" style="font-family:'Weissrundgotisch';line-height:.9em;">Transaction {{ transaction[0] }}</h1>
|
||||
</div>
|
||||
|
||||
<div class="row m-0 border-secondary border-top">
|
||||
<div class="text-white mb-0 border-bottom border-secondary lead-text" style="width:100%;">
|
||||
<ul>
|
||||
<li>Block: <a href="../block/{{ transaction[1] }}">{{ transaction[1] }}</a></li>
|
||||
<li>Payload: {{ transaction[2] }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user