mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2024-09-21 00:24:37 +03:00
Display best iters in UI
This commit is contained in:
parent
51ab6260dc
commit
053185265e
@ -66,7 +66,8 @@
|
||||
<tr>
|
||||
<th scope="col">Block hash</th>
|
||||
<th scope="col" style="width: 100px;">Height</th>
|
||||
<th scope="col" style-"width: 200px;">Time created</th>
|
||||
<th scope="col" style="">Time created</th>
|
||||
<th scope="col" style="">Expected VDF finish</th>
|
||||
</tr>
|
||||
<tbody id="latest-blocks-tbody">
|
||||
</tbody>
|
||||
|
@ -16,6 +16,11 @@ class FullNodeRpcClient {
|
||||
"header_hash": header_hash,
|
||||
});
|
||||
}
|
||||
async get_unfinished_block_headers(height) {
|
||||
return await this.make_request("get_unfinished_block_headers", {
|
||||
"height": height,
|
||||
});
|
||||
}
|
||||
|
||||
async get_block(header_hash) {
|
||||
return await this.make_request("get_block", {
|
||||
|
@ -72,7 +72,7 @@ async function render() {
|
||||
block_tbody.appendChild(create_table_row("Cost", block.header.data.cost));
|
||||
block_tbody.appendChild(create_table_row("Difficulty", BigInt(diff).toLocaleString()));
|
||||
block_tbody.appendChild(create_table_row("Total VDF Iterations", BigInt(block.header.data.total_iters).toLocaleString()));
|
||||
block_tbody.appendChild(create_table_row("Block VDF Iterations", block.proof_of_time.number_of_iterations));
|
||||
block_tbody.appendChild(create_table_row("Block VDF Iterations", BigInt(block.proof_of_time.number_of_iterations).toLocaleString()));
|
||||
block_tbody.appendChild(create_table_row("Proof of Space Size", block.proof_of_space.size));
|
||||
block_tbody.appendChild(create_table_row("Plot Public Key", block.proof_of_space.plot_pubkey));
|
||||
block_tbody.appendChild(create_table_row("Pool Public Key", block.proof_of_space.pool_pubkey));
|
||||
|
@ -37,6 +37,7 @@ class FullNodeView {
|
||||
this.state = {
|
||||
tip_hashes: new Set(),
|
||||
getting_info: false,
|
||||
getting_info_unfinished: false,
|
||||
connections: {},
|
||||
displayed_connections: new Set(),
|
||||
max_height: 0,
|
||||
@ -48,11 +49,14 @@ class FullNodeView {
|
||||
ips: 0,
|
||||
min_iters: 0,
|
||||
latest_blocks: [],
|
||||
latest_unfinished_blocks: [],
|
||||
}
|
||||
this.update_view(true);
|
||||
this.initialize_handlers();
|
||||
this.get_info();
|
||||
this.get_info_unfinished();
|
||||
this.interval = setInterval(() => this.get_info(), 2000);
|
||||
this.interval = setInterval(() => this.get_info_unfinished(), 7000);
|
||||
}
|
||||
|
||||
initialize_handlers() {
|
||||
@ -164,6 +168,54 @@ class FullNodeView {
|
||||
return blocks;
|
||||
}
|
||||
|
||||
async get_latest_unfinished_blocks(tips, ips) {
|
||||
let num_headers_to_display = 3;
|
||||
let min_height = 9999999999;
|
||||
let max_height = 0;
|
||||
for (let tip of tips) {
|
||||
if (tip.data.height < min_height) min_height = tip.data.height;
|
||||
if (tip.data.height > max_height) max_height = tip.data.height;
|
||||
}
|
||||
let headers = [];
|
||||
for (let height=max_height + 1; height >= min_height; height--) {
|
||||
let fetched = await rpc_client.get_unfinished_block_headers(height);
|
||||
for (let fetched_h of fetched) {
|
||||
fetched_h.header_hash = await hash_header(fetched_h);
|
||||
headers.push(fetched_h);
|
||||
}
|
||||
if (headers.length >= num_headers_to_display) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Get prev headers to check iterations required for this block
|
||||
let iters_map = {};
|
||||
for (let header of headers) {
|
||||
let prev = await rpc_client.get_header(header.data.prev_header_hash);
|
||||
iters_map[header.header_hash] = BigInt(header.data.total_iters) - BigInt(prev.data.total_iters);
|
||||
}
|
||||
let blocks = [];
|
||||
// Add the expected_finish property to each header
|
||||
for (let i=0; i < headers.length; i++) {
|
||||
let iters = iters_map[headers[i].header_hash];
|
||||
let finish_time = BigInt(headers[i].data.timestamp) + BigInt(iters) / BigInt(ips);
|
||||
blocks.push({
|
||||
"header_hash": headers[i].header_hash,
|
||||
"header": headers[i],
|
||||
"expected_finish": finish_time,
|
||||
"iters": iters,
|
||||
})
|
||||
}
|
||||
|
||||
// Sort by block height, then expected finish time
|
||||
blocks.sort((b1, b2) => {
|
||||
if (b2.header.data.height != b1.header.data.height) {
|
||||
return b2.header.data.height - b1.header.data.height;
|
||||
}
|
||||
return Number(b1.expected_finish - b2.expected_finish);
|
||||
})
|
||||
return blocks.slice(0, num_headers_to_display);
|
||||
}
|
||||
|
||||
create_table_cell(text) {
|
||||
let cell = document.createElement("td");
|
||||
let cellText = document.createTextNode(text);
|
||||
@ -211,7 +263,14 @@ class FullNodeView {
|
||||
}
|
||||
if (redisplay_blocks) {
|
||||
latest_blocks_tbody.innerHTML = "";
|
||||
for (let block of this.state.latest_blocks) {
|
||||
let display_blocks = this.state.latest_unfinished_blocks.concat(this.state.latest_blocks);
|
||||
let latest_blocks_hh = this.state.latest_blocks.map((b) => b.header_hash);
|
||||
|
||||
for (let block of display_blocks) {
|
||||
if ("expected_finish" in block && latest_blocks_hh.includes(block.header_hash)) {
|
||||
// Don't display unfinished blocks that are already in finished blocks list
|
||||
continue;
|
||||
}
|
||||
let row = document.createElement("tr");
|
||||
let link = document.createElement("a");
|
||||
let action_cell = document.createElement("td");
|
||||
@ -227,12 +286,21 @@ class FullNodeView {
|
||||
if (hh === this.state.lca_hash) {
|
||||
height_str += " (LCA)";
|
||||
}
|
||||
link.innerHTML = block.header_hash;
|
||||
link.innerHTML = block.header_hash.substring(0, 5) + "..." + block.header_hash.substring(59);
|
||||
link.style.textDecoration = "underline";
|
||||
action_cell.appendChild(link);
|
||||
row.appendChild(action_cell);
|
||||
row.appendChild(this.create_table_cell(height_str));
|
||||
row.appendChild(this.create_table_cell(unix_to_short_date(block.header.data.timestamp)));
|
||||
if ("expected_finish" in block) {
|
||||
row.append(this.create_table_cell(link.innerHTML))
|
||||
row.appendChild(this.create_table_cell(height_str + " (unfinished)"));
|
||||
row.appendChild(this.create_table_cell(unix_to_short_date(block.header.data.timestamp)));
|
||||
row.appendChild(this.create_table_cell(unix_to_short_date(block.expected_finish.toString()) + " (" + BigInt(block.iters).toLocaleString() + " iter)"));
|
||||
row.style.color = "orange";
|
||||
} else {
|
||||
row.appendChild(action_cell);
|
||||
row.appendChild(this.create_table_cell(height_str));
|
||||
row.appendChild(this.create_table_cell(unix_to_short_date(block.header.data.timestamp)));
|
||||
row.appendChild(this.create_table_cell("Finished"));
|
||||
}
|
||||
latest_blocks_tbody.appendChild(row);
|
||||
}
|
||||
}
|
||||
@ -287,6 +355,36 @@ class FullNodeView {
|
||||
}
|
||||
this.state.getting_info = false;
|
||||
};
|
||||
|
||||
async get_info_unfinished() {
|
||||
if ((max_block_height_textfield === undefined) || (max_block_height_textfield === null)) {
|
||||
// Stop the interval if we changed tabs.
|
||||
this.stop();
|
||||
return;
|
||||
}
|
||||
if (this.state.getting_info_unfinished) {
|
||||
return;
|
||||
}
|
||||
this.state.getting_info_unfinished = true;
|
||||
try {
|
||||
let blockchain_state = await rpc_client.get_blockchain_state();
|
||||
let unfinished_blocks = await this.get_latest_unfinished_blocks(blockchain_state.tips, blockchain_state.ips);
|
||||
let update = false;
|
||||
for (let b of unfinished_blocks) {
|
||||
if (!this.state.latest_unfinished_blocks.map(x => x.header_hash).includes(b.header_hash)) {
|
||||
update = true;
|
||||
this.state.latest_unfinished_blocks = unfinished_blocks;
|
||||
break;
|
||||
}
|
||||
}
|
||||
await this.update_view(update);
|
||||
} catch (error) {
|
||||
console.error("Error getting unfinished info from node", error);
|
||||
this.node_not_connected();
|
||||
}
|
||||
this.state.getting_info_unfinished = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!(max_block_height_textfield === undefined) && !(max_block_height_textfield === null)) {
|
||||
|
@ -228,7 +228,9 @@ async def show_async(args, parser):
|
||||
result_txt = f"NodeID {args.remove_connection}... not found."
|
||||
print(result_txt)
|
||||
if args.block_header_hash != "":
|
||||
block_header = await client.get_block(hexstr_to_bytes(args.block_header_hash))
|
||||
block_header = await client.get_block(
|
||||
hexstr_to_bytes(args.block_header_hash)
|
||||
)
|
||||
# print(dir(block_header))
|
||||
if block_header is not None:
|
||||
print("Block header:")
|
||||
@ -256,7 +258,7 @@ async def show_async(args, parser):
|
||||
f"Difficulty {block.header.data.weight-prev_block_header.header.data.weight}\n"
|
||||
f"Total VDF Iterations {block.header.data.total_iters}\n"
|
||||
f"Block VDF Iterations {block.proof_of_time.number_of_iterations}\n"
|
||||
f"Proof of Space \'k\' Size {block.proof_of_space.size}\n"
|
||||
f"Proof of Space 'k' Size {block.proof_of_space.size}\n"
|
||||
# f"Plot Public Key 0x{block.proof_of_space.plot_pubkey}\n"
|
||||
# f"Pool Public Key 0x{block.proof_of_space.pool_pubkey}\n"
|
||||
f"Tx Filter Hash {(block.transactions_filter)}\n"
|
||||
|
@ -6,7 +6,7 @@ from src.util.byte_types import hexstr_to_bytes
|
||||
from src.types.full_block import FullBlock
|
||||
from src.types.header import Header
|
||||
from src.types.sized_bytes import bytes32
|
||||
from src.util.ints import uint16
|
||||
from src.util.ints import uint16, uint32
|
||||
from src.types.coin_record import CoinRecord
|
||||
|
||||
|
||||
@ -62,6 +62,10 @@ class RpcClient:
|
||||
raise
|
||||
return Header.from_json_dict(response)
|
||||
|
||||
async def get_unfinished_block_headers(self, height: uint32) -> List[Header]:
|
||||
response = await self.fetch("get_unfinished_block_headers", {"height": height})
|
||||
return [Header.from_json_dict(r) for r in response]
|
||||
|
||||
async def get_connections(self) -> List[Dict]:
|
||||
response = await self.fetch("get_connections", {})
|
||||
for connection in response:
|
||||
|
@ -110,6 +110,18 @@ class RpcApiHandler:
|
||||
raise web.HTTPNotFound()
|
||||
return obj_to_response(header)
|
||||
|
||||
async def get_unfinished_block_headers(self, request) -> web.Response:
|
||||
request_data = await request.json()
|
||||
if "height" not in request_data:
|
||||
raise web.HTTPBadRequest()
|
||||
height = request_data["height"]
|
||||
response_headers: List[Header] = []
|
||||
for block in (self.full_node.store.get_unfinished_blocks()).values():
|
||||
if block.height == height:
|
||||
response_headers.append(block.header)
|
||||
|
||||
return obj_to_response(response_headers)
|
||||
|
||||
async def get_connections(self, request) -> web.Response:
|
||||
"""
|
||||
Retrieves all connections to this full node, including farmers and timelords.
|
||||
@ -228,6 +240,9 @@ async def start_rpc_server(
|
||||
web.post("/get_blockchain_state", handler.get_blockchain_state),
|
||||
web.post("/get_block", handler.get_block),
|
||||
web.post("/get_header", handler.get_header),
|
||||
web.post(
|
||||
"/get_unfinished_block_headers", handler.get_unfinished_block_headers
|
||||
),
|
||||
web.post("/get_connections", handler.get_connections),
|
||||
web.post("/open_connection", handler.open_connection),
|
||||
web.post("/close_connection", handler.close_connection),
|
||||
|
@ -314,6 +314,7 @@ class ChiaServer:
|
||||
async def serve_forever():
|
||||
async for connection, message in expanded_messages_aiter:
|
||||
if message is None:
|
||||
# Does not ban the peer, this is just a graceful close of connection.
|
||||
self.global_connections.close(connection, True)
|
||||
continue
|
||||
self.log.info(
|
||||
@ -518,6 +519,7 @@ class ChiaServer:
|
||||
except Exception:
|
||||
tb = traceback.format_exc()
|
||||
self.log.error(f"Error, closing connection {connection}. {tb}")
|
||||
# TODO: Exception means peer gave us invalid information, so ban this peer.
|
||||
self.global_connections.close(connection)
|
||||
|
||||
async def expand_outbound_messages(
|
||||
@ -556,4 +558,5 @@ class ChiaServer:
|
||||
else:
|
||||
yield (peer, outbound_message.message)
|
||||
elif outbound_message.delivery_method == Delivery.CLOSE:
|
||||
# Close the connection but don't ban the peer
|
||||
yield (connection, None)
|
||||
|
@ -29,6 +29,10 @@ class TestRpc:
|
||||
blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10)
|
||||
|
||||
for i in range(1, num_blocks):
|
||||
async for _ in full_node_1.respond_unfinished_block(
|
||||
full_node_protocol.RespondUnfinishedBlock(blocks[i])
|
||||
):
|
||||
pass
|
||||
async for _ in full_node_1.respond_block(
|
||||
full_node_protocol.RespondBlock(blocks[i])
|
||||
):
|
||||
@ -54,6 +58,10 @@ class TestRpc:
|
||||
assert block == blocks[7]
|
||||
assert (await client.get_block(bytes([1] * 32))) is None
|
||||
|
||||
unf_block_headers = await client.get_unfinished_block_headers(5)
|
||||
assert len(unf_block_headers) == 1
|
||||
assert unf_block_headers[0] == blocks[5].header
|
||||
|
||||
header = await client.get_header(state["lca"].header_hash)
|
||||
assert header == blocks[7].header
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user