explorer: display slot leaders on block details page (#24727)

This commit is contained in:
Justin Starry 2022-04-27 12:57:18 +08:00 committed by GitHub
parent f22738fd7b
commit 4e2d96fe88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 78 additions and 23 deletions

View File

@ -14,6 +14,7 @@ import { BlockProgramsCard } from "./BlockProgramsCard";
import { BlockAccountsCard } from "./BlockAccountsCard";
import { displayTimestamp, displayTimestampUtc } from "utils/date";
import { Epoch } from "components/common/Epoch";
import { Address } from "components/common/Address";
export function BlockOverviewCard({
slot,
@ -43,7 +44,8 @@ export function BlockOverviewCard({
return <ErrorCard retry={refresh} text={`Block ${slot} was not found`} />;
}
const block = confirmedBlock.data.block;
const { block, blockLeader, childSlot, childLeader, parentLeader } =
confirmedBlock.data;
const committedTxs = block.transactions.filter((tx) => tx.meta?.err === null);
const epoch = clusterInfo?.epochSchedule.getEpoch(slot);
@ -56,18 +58,26 @@ export function BlockOverviewCard({
</h3>
</div>
<TableCardBody>
<tr>
<td className="w-100">Slot</td>
<td className="text-lg-end font-monospace">
<Slot slot={slot} />
</td>
</tr>
<tr>
<td className="w-100">Blockhash</td>
<td className="text-lg-end font-monospace">
<span>{block.blockhash}</span>
</td>
</tr>
<tr>
<td className="w-100">Slot</td>
<td className="text-lg-end font-monospace">
<Slot slot={slot} />
</td>
</tr>
{blockLeader !== undefined && (
<tr>
<td className="w-100">Slot Leader</td>
<td className="text-lg-end">
<Address pubkey={blockLeader} alignRight link />
</td>
</tr>
)}
{block.blockTime ? (
<>
<tr>
@ -93,12 +103,6 @@ export function BlockOverviewCard({
<td className="text-lg-end">Unavailable</td>
</tr>
)}
<tr>
<td className="w-100">Parent Slot</td>
<td className="text-lg-end font-monospace">
<Slot slot={block.parentSlot} link />
</td>
</tr>
{epoch !== undefined && (
<tr>
<td className="w-100">Epoch</td>
@ -113,11 +117,33 @@ export function BlockOverviewCard({
<span>{block.previousBlockhash}</span>
</td>
</tr>
{confirmedBlock.data.child && (
<tr>
<td className="w-100">Parent Slot</td>
<td className="text-lg-end font-monospace">
<Slot slot={block.parentSlot} link />
</td>
</tr>
{parentLeader !== undefined && (
<tr>
<td className="w-100">Parent Slot Leader</td>
<td className="text-lg-end">
<Address pubkey={parentLeader} alignRight link />
</td>
</tr>
)}
{childSlot !== undefined && (
<tr>
<td className="w-100">Child Slot</td>
<td className="text-lg-end font-monospace">
<Slot slot={confirmedBlock.data.child} link />
<Slot slot={childSlot} link />
</td>
</tr>
)}
{childLeader !== undefined && (
<tr>
<td className="w-100">Child Slot Leader</td>
<td className="text-lg-end">
<Address pubkey={childLeader} alignRight link />
</td>
</tr>
)}

View File

@ -1,7 +1,7 @@
import React from "react";
import * as Sentry from "@sentry/react";
import * as Cache from "providers/cache";
import { Connection, BlockResponse } from "@solana/web3.js";
import { Connection, BlockResponse, PublicKey } from "@solana/web3.js";
import { useCluster, Cluster } from "./cluster";
export enum FetchStatus {
@ -17,7 +17,10 @@ export enum ActionType {
type Block = {
block?: BlockResponse;
child?: number;
blockLeader?: PublicKey;
childSlot?: number;
childLeader?: PublicKey;
parentLeader?: PublicKey;
};
type State = Cache.State<Block>;
@ -59,12 +62,12 @@ export async function fetchBlock(
dispatch: Dispatch,
url: string,
cluster: Cluster,
key: number
slot: number
) {
dispatch({
type: ActionType.Update,
status: FetchStatus.Fetching,
key,
key: slot,
url,
});
@ -73,13 +76,39 @@ export async function fetchBlock(
try {
const connection = new Connection(url, "confirmed");
const block = await connection.getBlock(key);
const child = (await connection.getBlocks(key + 1, key + 100)).shift();
const block = await connection.getBlock(slot);
if (block === null) {
data = {};
status = FetchStatus.Fetched;
} else {
data = { block, child };
const childSlot = (
await connection.getBlocks(slot + 1, slot + 100)
).shift();
const firstLeaderSlot = block.parentSlot;
let leaders: PublicKey[] = [];
try {
const lastLeaderSlot = childSlot !== undefined ? childSlot : slot;
const slotLeadersLimit = lastLeaderSlot - block.parentSlot + 1;
leaders = await connection.getSlotLeaders(
firstLeaderSlot,
slotLeadersLimit
);
} catch (err) {
// ignore errors
}
const getLeader = (slot: number) => {
return leaders.at(slot - firstLeaderSlot);
};
data = {
block,
blockLeader: getLeader(slot),
childSlot,
childLeader: childSlot !== undefined ? getLeader(childSlot) : undefined,
parentLeader: getLeader(block.parentSlot),
};
status = FetchStatus.Fetched;
}
} catch (err) {
@ -92,7 +121,7 @@ export async function fetchBlock(
dispatch({
type: ActionType.Update,
url,
key,
key: slot,
status,
data,
});