From 4e2d96fe88745fb4438da8b3a490d43c8cef6703 Mon Sep 17 00:00:00 2001 From: Justin Starry Date: Wed, 27 Apr 2022 12:57:18 +0800 Subject: [PATCH] explorer: display slot leaders on block details page (#24727) --- .../components/block/BlockOverviewCard.tsx | 52 ++++++++++++++----- explorer/src/providers/block.tsx | 45 +++++++++++++--- 2 files changed, 76 insertions(+), 21 deletions(-) diff --git a/explorer/src/components/block/BlockOverviewCard.tsx b/explorer/src/components/block/BlockOverviewCard.tsx index f129bc98c706d7..9be7cf0fae5282 100644 --- a/explorer/src/components/block/BlockOverviewCard.tsx +++ b/explorer/src/components/block/BlockOverviewCard.tsx @@ -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 ; } - 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); @@ -57,17 +59,25 @@ export function BlockOverviewCard({ - Slot + Blockhash - + {block.blockhash} - Blockhash + Slot - {block.blockhash} + + {blockLeader !== undefined && ( + + Slot Leader + +
+ + + )} {block.blockTime ? ( <> @@ -93,12 +103,6 @@ export function BlockOverviewCard({ Unavailable )} - - Parent Slot - - - - {epoch !== undefined && ( Epoch @@ -113,11 +117,33 @@ export function BlockOverviewCard({ {block.previousBlockhash} - {confirmedBlock.data.child && ( + + Parent Slot + + + + + {parentLeader !== undefined && ( + + Parent Slot Leader + +
+ + + )} + {childSlot !== undefined && ( Child Slot - + + + + )} + {childLeader !== undefined && ( + + Child Slot Leader + +
)} diff --git a/explorer/src/providers/block.tsx b/explorer/src/providers/block.tsx index 724132bb25411f..fa1b564950ddfc 100644 --- a/explorer/src/providers/block.tsx +++ b/explorer/src/providers/block.tsx @@ -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; @@ -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, });