Skip to content

Client diversity piechart update #15251

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 52 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
4bb1a87
Created React PieChart component
LifeofDan-EL Apr 7, 2025
11827ed
Merge branch 'ethereum:dev' into client-diversity
LifeofDan-EL Apr 7, 2025
1553d14
Testing to see if the chart works, before removing and updating the d…
LifeofDan-EL Apr 7, 2025
fb4c103
Merge branch 'client-diversity' of https://github.com/LifeofDan-EL/et…
LifeofDan-EL Apr 7, 2025
84292b1
Fix lint errors
LifeofDan-EL Apr 7, 2025
480a1e1
Fix lint errors
LifeofDan-EL Apr 7, 2025
45761c8
Changed import way for the PieChart
LifeofDan-EL Apr 8, 2025
0c8ac7c
Revert yarn.lock and .env.example to match upstream/dev
LifeofDan-EL Apr 8, 2025
99615fa
Merge branch 'ethereum:dev' into client-diversity
LifeofDan-EL Apr 8, 2025
202418c
Improved PieChart
LifeofDan-EL Apr 8, 2025
f8d0a70
Fixing import issue
LifeofDan-EL Apr 8, 2025
171eefa
Slight improvement on the PieChart
LifeofDan-EL Apr 8, 2025
f689074
Merge branch 'ethereum:dev' into client-diversity
LifeofDan-EL Apr 11, 2025
1ce8c30
Delete .yarnrc.yml
LifeofDan-EL Apr 11, 2025
73091d9
Delete .yarn directory
LifeofDan-EL Apr 11, 2025
1f0116e
Updated styling to use color palette
LifeofDan-EL Apr 11, 2025
cbe8b2e
Changed to accent colors
LifeofDan-EL Apr 12, 2025
7cfd42c
Remove sticking out label, then attaching the percentage value to the…
LifeofDan-EL Apr 12, 2025
352ed27
Trying to fix payload issue
LifeofDan-EL Apr 12, 2025
c57d2c2
Added ResponsiveContainer to PieChart
LifeofDan-EL Apr 16, 2025
8c7ad14
Working on responsiveness
LifeofDan-EL Apr 16, 2025
c112033
Working on responsiveness
LifeofDan-EL Apr 16, 2025
a6b359b
Working on responsiveness
LifeofDan-EL Apr 16, 2025
57ec8f0
Working on responsiveness
LifeofDan-EL Apr 16, 2025
8ffc3da
Working on responsiveness
LifeofDan-EL Apr 16, 2025
7e6926d
Working on responsiveness
LifeofDan-EL Apr 16, 2025
ce7e234
Working on responsiveness
LifeofDan-EL Apr 16, 2025
d8b85c6
Still working on it
LifeofDan-EL Apr 16, 2025
64c2c57
Working on responsiveness
LifeofDan-EL Apr 16, 2025
d2b2910
Working on responsiveness
LifeofDan-EL Apr 16, 2025
003b4d0
Testing for responsiveness
LifeofDan-EL Apr 16, 2025
b697fe3
Updated content
LifeofDan-EL Apr 18, 2025
e0d3b85
Merge branch 'ethereum:dev' into client-diversity
LifeofDan-EL Apr 18, 2025
9724d25
Formatted footnote better
LifeofDan-EL Apr 18, 2025
dfdfc39
Merge branch 'client-diversity' of https://github.com/LifeofDan-EL/et…
LifeofDan-EL Apr 18, 2025
8273f9f
Working on footnote issue
LifeofDan-EL Apr 18, 2025
4975d85
Working on footnote
LifeofDan-EL Apr 19, 2025
a7545d6
Fixed typo
LifeofDan-EL Apr 19, 2025
40900c1
Merge branch 'ethereum:dev' into client-diversity
LifeofDan-EL Apr 30, 2025
5b009cc
Legend line height reduction
LifeofDan-EL Apr 30, 2025
237b975
Fix build error
LifeofDan-EL Apr 30, 2025
61c1c28
Footnote correction
LifeofDan-EL Apr 30, 2025
3d466f3
Working on responsiveness
LifeofDan-EL Apr 30, 2025
a21a28e
Working on responsiveness
LifeofDan-EL Apr 30, 2025
7c3a882
Modified PieChart
LifeofDan-EL Apr 30, 2025
10807d3
Fix build error
LifeofDan-EL Apr 30, 2025
3f7ebbb
Fixing unused parameter
LifeofDan-EL Apr 30, 2025
4c7f147
Working on it
LifeofDan-EL Apr 30, 2025
6c49948
Trying new approach
LifeofDan-EL Apr 30, 2025
1832679
Testing
LifeofDan-EL Apr 30, 2025
08b3fa2
Updating client diversity
LifeofDan-EL Jun 21, 2025
039d48d
Merge branch 'client-diversity' of https://github.com/LifeofDan-EL/et…
LifeofDan-EL Jun 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions .prettierrc

This file was deleted.

Binary file added .yarn/install-state.gz
Binary file not shown.
1 change: 1 addition & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nodeLinker: node-modules
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,19 @@ Although these are unlikely scenarios, the Ethereum eco-system can mitigate thei

There is also a human cost to having majority clients. It puts excess strain and responsibility on a small development team. The lesser the client diversity, the greater the burden of responsibility for the developers maintaining the majority client. Spreading this responsibility across multiple teams is good for both the health of Ethereum's network of nodes and its network of people.

## Current client diversity {#current-client-diversity}
### Current client diversity {#current-client-diversity}

![Pie chart showing client diversity](./client-diversity.png)
_Diagram data from [ethernodes.org](https://ethernodes.org) and [clientdiversity.org](https://clientdiversity.org/)_
<PieChartContainer />

The two pie charts above show snapshots of the current client diversity for the execution and consensus layers (at time of writing in January 2022). The execution layer is overwhelmingly dominated by [Geth](https://geth.ethereum.org/), with [Open Ethereum](https://openethereum.github.io/) a distant second, [Erigon](https://github.com/ledgerwatch/erigon) third and [Nethermind](https://nethermind.io/) fourth, with other clients comprising less than 1 % of the network. The most commonly used client on the consensus layer - [Prysm](https://prysmaticlabs.com/#projects) - is not as dominant as Geth but still represents over 60% of the network. [Lighthouse](https://lighthouse.sigmaprime.io/) and [Teku](https://consensys.net/knowledge-base/ethereum-2/teku/) make up ~20% and ~14% respectively, and other clients are rarely used.
The two pie charts above show snapshots of the current client diversity for the execution and consensus layers (at time of writing in June 2025). Client diversity has improved over the years, and the execution layer has seen a reduction in the domination by [Geth](https://geth.ethereum.org/), with [Nethermind](https://www.nethermind.io/nethermind-client) a close second, [Besu](https://besu.hyperledger.org/) third and [Erigon](https://github.com/ledgerwatch/erigon) fourth, with other clients comprising less than 3 % of the network. The most commonly used client on the consensus layer - [Lighthouse](https://lighthouse.sigmaprime.io/) - is quite close with the second most used.[Prysm](https://prysmaticlabs.com/#projects) and [Teku](https://consensys.net/knowledge-base/ethereum-2/teku/) make up ~31% and ~14% respectively, and other clients are rarely used.

The execution layer data were obtained from [Ethernodes](https://ethernodes.org) on 23-Jan-2022. Data for consensus clients was obtained from [Michael Sproul](https://github.com/sigp/blockprint). Consensus client data is more difficult to obtain because the consensus layer clients do not always have unambiguous traces that can be used to identify them. The data was generated using a classification algorithm that sometimes confuses some of the minority clients (see [here](https://twitter.com/sproulM_/status/1440512518242197516) for more details). In the diagram above, these ambiguous classifications are treated with an either/or label (e.g. Nimbus/Teku). Nevertheless, it is clear that the majority of the network is running Prysm. The data is a snapshot over a fixed set of blocks (in this case Beacon blocks in slots 2048001 to 2164916) and Prysm's dominance has sometimes been higher, exceeding 68%. Despite only being snapshots, the values in the diagram provide a good general sense of the current state of client diversity.
The execution layer data were obtained from [supermajority.info](https://supermajority.info/) on 21-Jun-2025. Data for consensus clients was obtained from [Michael Sproul](https://github.com/sigp/blockprint). Consensus client data is more difficult to obtain because the consensus layer clients do not always have unambiguous traces that can be used to identify them. The data was generated using a classification algorithm that sometimes confuses some of the minority clients (see [here](https://twitter.com/sproulM_/status/1440512518242197516) for more details). In the diagram above, these ambiguous classifications are treated with an either/or label (e.g. Nimbus/Teku). Nevertheless, it is clear that the majority of the network is running Prysm. Despite only being snapshots, the values in the diagram provide a good general sense of the current state of client diversity.

Up to date client diversity data for the consensus layer is now available at [clientdiversity.org](https://clientdiversity.org/).

## Execution layer {#execution-layer}

Until now, the conversation around client diversity has focused mainly on the consensus layer. However, the execution client [Geth](https://geth.ethereum.org) currently accounts for around 85% of all nodes. This percentage is problematic for the same reasons as for consensus clients. For example, a bug in Geth affecting transaction handling or constructing execution payloads could lead to consensus clients finalizing problematic or bugged transactions. Therefore, Ethereum would be healthier with a more even distribution of execution clients, ideally with no client representing more than 33% of the network.
Until now, the conversation around client diversity has focused mainly on the consensus layer. However, the execution client [Geth](https://geth.ethereum.org) currently accounts for around 41% of all nodes. This percentage is problematic for the same reasons as for consensus clients. For example, a bug in Geth affecting transaction handling or constructing execution payloads could lead to consensus clients finalizing problematic or bugged transactions. Therefore, Ethereum would be healthier with a more even distribution of execution clients, ideally with no client representing more than 33% of the network.

## Use a minority client {#use-minority-client}

Expand All @@ -66,6 +65,8 @@ Addressing client diversity requires more than individual users to choose minori

[Erigon](https://github.com/ledgerwatch/erigon)

[Reth](https://github.com/paradigmxyz/reth)

[Go-Ethereum](https://geth.ethereum.org/)

### Consensus clients {#consensus-clients}
Expand Down
96 changes: 49 additions & 47 deletions src/components/MdComponents/index.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,34 @@
import { type ComponentProps, type HTMLAttributes } from "react"

import type { ChildOnlyProp } from "@/lib/types"

import Contributors from "@/components/Contributors"
import MarkdownImage from "@/components/Image/MarkdownImage"
import TooltipLink from "@/components/TooltipLink"
import YouTube from "@/components/YouTube"

import { cn } from "@/lib/utils/cn"

import ContributorsQuizBanner from "../Banners/ContributorsQuizBanner"
import Card from "../Card"
import DocLink from "../DocLink"
import Emoji from "../Emoji"
import ExpandableCard from "../ExpandableCard"
import FeaturedText from "../FeaturedText"
import GlossaryTooltip from "../Glossary/GlossaryTooltip"
import IdAnchor from "../IdAnchor"
import InfoBanner from "../InfoBanner"
import IssuesList from "../IssuesList"
import LocaleDateTime from "../LocaleDateTime"
import MainArticle from "../MainArticle"
import { StandaloneQuizWidget } from "../Quiz/QuizWidget"
import { ButtonLink } from "../ui/buttons/Button"
import { Divider } from "../ui/divider"
import { Flex } from "../ui/flex"
import { ListItem, OrderedList, UnorderedList } from "../ui/list"
import { mdxTableComponents } from "../ui/mdx-table-components"
import { Tag } from "../ui/tag"
import { type ComponentProps, type HTMLAttributes } from "react";

import type { ChildOnlyProp } from "@/lib/types";

import Contributors from "@/components/Contributors";
import TooltipLink from "@/components/TooltipLink";
import YouTube from "@/components/YouTube";

import { cn } from "@/lib/utils/cn";

import ContributorsQuizBanner from "../Banners/ContributorsQuizBanner";
import Card from "../Card";
import DocLink from "../DocLink";
import Emoji from "../Emoji";
import ExpandableCard from "../ExpandableCard";
import FeaturedText from "../FeaturedText";
import GlossaryTooltip from "../Glossary/GlossaryTooltip";
import IdAnchor from "../IdAnchor";
import MarkdownImage from "../Image/MarkdownImage";
import InfoBanner from "../InfoBanner";
import IssuesList from "../IssuesList";
import LocaleDateTime from "../LocaleDateTime";
import MainArticle from "../MainArticle";
import PieChartContainer from "../PieChart";
import { StandaloneQuizWidget } from "../Quiz/QuizWidget";
import { ButtonLink } from "../ui/buttons/Button";
import { Divider } from "../ui/divider";
import { Flex } from "../ui/flex";
import { ListItem, OrderedList, UnorderedList } from "../ui/list";
import { mdxTableComponents } from "../ui/mdx-table-components";
import { Tag } from "../ui/tag";

export const commonHeadingAttributes = (className: string, id?: string) => ({
id,
Expand All @@ -37,15 +38,15 @@ export const commonHeadingAttributes = (className: string, id?: string) => ({
className
),
"data-group": !!id || undefined,
})
});

type HeadingProps = HTMLAttributes<HTMLHeadingElement>
type HeadingProps = HTMLAttributes<HTMLHeadingElement>;

export const Heading1 = ({ children, className, ...rest }: HeadingProps) => (
<h1 {...commonHeadingAttributes(cn("text-[2.5rem]", className))} {...rest}>
{children}
</h1>
)
);

export const Heading2 = ({
id,
Expand All @@ -60,7 +61,7 @@ export const Heading2 = ({
<IdAnchor id={id} />
{children}
</h2>
)
);

export const Heading3 = ({
id,
Expand All @@ -75,7 +76,7 @@ export const Heading3 = ({
<IdAnchor id={id} />
{children}
</h3>
)
);

export const Heading4 = ({
id,
Expand All @@ -90,22 +91,22 @@ export const Heading4 = ({
<IdAnchor id={id} />
{children}
</h4>
)
);

export const Pre = (props: ChildOnlyProp) => (
<pre
className="max-w-full overflow-x-scroll whitespace-pre-wrap rounded border bg-background-highlight p-4"
{...props}
/>
)
);

export const Paragraph = (props: ChildOnlyProp) => (
<p className="mb-4 mt-8" {...props} />
)
);

export const HR = () => (
<hr className="mb-4 mt-8 inline-block w-full border-body-medium opacity-60" />
)
);

// All base html element components
export const htmlElements = {
Expand All @@ -123,7 +124,7 @@ export const htmlElements = {
time: LocaleDateTime,
ul: UnorderedList,
...mdxTableComponents,
}
};

/**
* Custom React components
Expand All @@ -139,17 +140,17 @@ export const Page = ({
)}
{...props}
/>
)
);

export const Title = (props: ChildOnlyProp) => (
<Heading1 className="mt-4" {...props} />
)
);

export const ContentContainer = (props: ComponentProps<"article">) => {
return (
<MainArticle className="relative flex-[1_1_992px] px-8 pb-8" {...props} />
)
}
);
};

// All custom React components
export const reactComponents = {
Expand All @@ -166,19 +167,20 @@ export const reactComponents = {
GlossaryTooltip,
InfoBanner,
Page,
PieChartContainer,
QuizWidget: StandaloneQuizWidget,
IssuesList,
Tag,
Title,
YouTube,
}
};

/**
* All base markdown components as default export
*/
const MdComponents = {
...htmlElements,
...reactComponents,
}
};

export default MdComponents
export default MdComponents;
Loading