Skip to content

Commit

Permalink
explorer: display slot leaders on block details page (#24727)
Browse files Browse the repository at this point in the history
  • Loading branch information
jstarry authored Apr 27, 2022
1 parent f22738f commit 4e2d96f
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 21 deletions.
52 changes: 39 additions & 13 deletions explorer/src/components/block/BlockOverviewCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);

Expand All @@ -57,17 +59,25 @@ export function BlockOverviewCard({
</div>
<TableCardBody>
<tr>
<td className="w-100">Slot</td>
<td className="w-100">Blockhash</td>
<td className="text-lg-end font-monospace">
<Slot slot={slot} />
<span>{block.blockhash}</span>
</td>
</tr>
<tr>
<td className="w-100">Blockhash</td>
<td className="w-100">Slot</td>
<td className="text-lg-end font-monospace">
<span>{block.blockhash}</span>
<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>
Expand All @@ -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>
Expand All @@ -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>
)}
Expand Down
45 changes: 37 additions & 8 deletions explorer/src/providers/block.tsx
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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>;
Expand Down Expand Up @@ -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,
});

Expand All @@ -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) {
Expand All @@ -92,7 +121,7 @@ export async function fetchBlock(
dispatch({
type: ActionType.Update,
url,
key,
key: slot,
status,
data,
});
Expand Down

1 comment on commit 4e2d96f

@denispalab
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for explorer ready!

✅ Preview
https://explorer-btepmwgnw-solana-labs.vercel.app

Built with commit 4e2d96f.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.