Skip to content

Commit 7a20c96

Browse files
leovctmds1
andauthored
feat: add execution and consensus nodes (#49)
* feat: add nodes * chore: clean up code * chore: reorganize code and separate execution and consensus nodes * fix: typo * chore: remove redundant node type * chore: update arbitrum nodes * fix: show diffs properly * fix: remove sync strategy field when not specified * feat: add `Language` enum * chore: add arbitrum nodes and add a new `forkOf` field for nodes * chore: update arbitrum nodes * chore: render `forkOf` * chore: lint * chore: remove op-node * style: simplify formatting --------- Co-authored-by: Matt Solomon <[email protected]>
1 parent a6f9235 commit 7a20c96

File tree

12 files changed

+308
-0
lines changed

12 files changed

+308
-0
lines changed

src/chains/arbitrum/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { sortedArrayByField, sortedArrayByFields } from '@/lib/utils';
33
import { Chain } from '@/types';
44
import { accountTypes } from './accountTypes';
55
import { deployedContracts } from './deployedContracts';
6+
import { consensusNodes, executionNodes } from './nodes';
67
import { signatureTypes } from './signatureTypes';
78
import { opcodes } from './vm/opcodes';
89
import { precompiles } from './vm/precompiles';
@@ -17,4 +18,6 @@ export const arbitrum: Chain = {
1718
opcodes: sortedArrayByField(opcodes, 'number'),
1819
mempools: [],
1920
deployedContracts: sortedArrayByFields(deployedContracts, ['kind', 'name']),
21+
executionNodes,
22+
consensusNodes,
2023
};

src/chains/arbitrum/nodes.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Language, Node, NodeType } from '@/types';
2+
3+
const nitro: Node = {
4+
name: 'nitro',
5+
description:
6+
'Nitro is the latest iteration of the Arbitrum technology. It is a fully integrated, complete layer 2 optimistic rollup system, including fraud proofs, the sequencer, the token bridges, advanced calldata compression, and more.',
7+
type: NodeType.Execution,
8+
language: Language.Go,
9+
repository: 'https://github.com/OffchainLabs/nitro',
10+
documentation: 'https://docs.arbitrum.io/',
11+
};
12+
13+
export const executionNodes: Node[] = [nitro];
14+
export const consensusNodes: Node[] = []; // Arbitrum does not have any consensus nodes.

src/chains/mainnet/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { Chain } from '@/types';
44
import { accountTypes } from './accountTypes';
55
import { deployedContracts } from './deployedContracts';
66
import { mempools } from './mempools';
7+
import { consensusNodes } from './nodes/consensus';
8+
import { executionNodes } from './nodes/execution';
79
import { signatureTypes } from './signatureTypes';
810
import { opcodes } from './vm/opcodes';
911
import { precompiles } from './vm/precompiles';
@@ -18,4 +20,6 @@ export const mainnet: Chain = {
1820
opcodes: sortedArrayByField(opcodes, 'number'),
1921
mempools: sortedArrayByField(mempools, 'name'),
2022
deployedContracts: sortedArrayByFields(deployedContracts, ['kind', 'name']),
23+
executionNodes,
24+
consensusNodes,
2125
};

src/chains/mainnet/nodes/consensus.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { Language, Node, NodeType } from '@/types';
2+
3+
const lighthouse: Node = {
4+
name: 'lighthouse',
5+
description: 'Ethereum consensus client in Rust.',
6+
type: NodeType.Consensus,
7+
language: Language.Rust,
8+
repository: 'https://github.com/sigp/lighthouse',
9+
documentation: 'https://lighthouse-book.sigmaprime.io/',
10+
};
11+
12+
const lodestar: Node = {
13+
name: 'lodestar',
14+
description: 'TypeScript Implementation of Ethereum Consensus.',
15+
type: NodeType.Consensus,
16+
language: Language.TypeScript,
17+
repository: 'https://github.com/ChainSafe/lodestar',
18+
documentation: 'https://lodestar.chainsafe.io/',
19+
};
20+
21+
const nimbus: Node = {
22+
name: 'nimbus',
23+
description: 'Nim implementation of the Ethereum Beacon Chain.',
24+
type: NodeType.Consensus,
25+
language: Language.Nim,
26+
repository: 'https://github.com/status-im/nimbus-eth2',
27+
documentation: 'https://nimbus.guide/',
28+
};
29+
30+
const prysm: Node = {
31+
name: 'prysm',
32+
description: 'Go implementation of Ethereum proof of stake.',
33+
type: NodeType.Consensus,
34+
language: Language.Go,
35+
repository: 'https://github.com/prysmaticlabs/prysm',
36+
documentation: 'https://prysmaticlabs.com/',
37+
};
38+
39+
const teku: Node = {
40+
name: 'teku',
41+
description: 'Java Implementation of the Ethereum 2.0 Beacon Chain.',
42+
type: NodeType.Consensus,
43+
language: Language.Java,
44+
repository: 'https://github.com/Consensys/teku',
45+
documentation: 'https://docs.teku.consensys.io/',
46+
};
47+
48+
export const consensusNodes: Node[] = [lighthouse, lodestar, nimbus, prysm, teku];

src/chains/mainnet/nodes/execution.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { Language, Node, NodeType, SyncStrategy } from '@/types';
2+
3+
const besu: Node = {
4+
name: 'besu',
5+
description: 'An enterprise-grade Java-based, Apache 2.0 licensed Ethereum client.',
6+
type: NodeType.Execution,
7+
language: Language.Java,
8+
syncStrategy: [SyncStrategy.Snap, SyncStrategy.Fast, SyncStrategy.Full],
9+
repository: 'https://github.com/hyperledger/besu',
10+
documentation: 'https://besu.hyperledger.org/',
11+
};
12+
13+
const coregeth: Node = {
14+
name: 'core-geth',
15+
description: 'A highly configurable Go implementation of the Ethereum protocol.',
16+
type: NodeType.Execution,
17+
language: Language.Go,
18+
syncStrategy: [SyncStrategy.Snap, SyncStrategy.Full],
19+
forkOf: 'geth',
20+
repository: 'https://github.com/etclabscore/core-geth',
21+
documentation: 'https://etclabscore.github.io/core-geth/',
22+
};
23+
24+
const erigon: Node = {
25+
name: 'erigon',
26+
description: 'Ethereum implementation on the efficiency frontier.',
27+
type: NodeType.Execution,
28+
language: Language.Go,
29+
syncStrategy: [SyncStrategy.Full],
30+
forkOf: 'geth',
31+
repository: 'https://github.com/ledgerwatch/erigon',
32+
documentation: 'https://erigon.gitbook.io/erigon/',
33+
};
34+
35+
const geth: Node = {
36+
name: 'geth',
37+
description: 'Official Go implementation of the Ethereum protocol.',
38+
type: NodeType.Execution,
39+
language: Language.Go,
40+
syncStrategy: [SyncStrategy.Snap, SyncStrategy.Full],
41+
repository: 'https://github.com/ethereum/go-ethereum',
42+
documentation: 'https://geth.ethereum.org/',
43+
};
44+
45+
export const nethermind: Node = {
46+
name: 'nethermind',
47+
description: 'A robust execution client for Ethereum node operators.',
48+
type: NodeType.Execution,
49+
language: Language.CSharp,
50+
syncStrategy: [SyncStrategy.Snap, SyncStrategy.Fast, SyncStrategy.Full],
51+
repository: 'https://github.com/NethermindEth/nethermind',
52+
documentation: 'https://docs.nethermind.io/',
53+
};
54+
55+
export const reth: Node = {
56+
name: 'reth',
57+
description:
58+
'Modular, contributor-friendly and blazing-fast implementation of the Ethereum protocol, in Rust.',
59+
type: NodeType.Execution,
60+
language: Language.Rust,
61+
syncStrategy: [SyncStrategy.Full],
62+
repository: 'https://github.com/paradigmxyz/reth',
63+
documentation: 'https://paradigmxyz.github.io/reth/',
64+
};
65+
66+
export const executionNodes: Node[] = [besu, coregeth, erigon, geth, nethermind, reth];

src/chains/optimism/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { sortedArrayByField, sortedArrayByFields } from '@/lib/utils';
33
import { Chain } from '@/types';
44
import { accountTypes } from './accountTypes';
55
import { deployedContracts } from './deployedContracts';
6+
import { consensusNodes, executionNodes } from './nodes';
67
import { signatureTypes } from './signatureTypes';
78
import { opcodes } from './vm/opcodes';
89
import { precompiles } from './vm/precompiles';
@@ -17,4 +18,6 @@ export const optimism: Chain = {
1718
opcodes: sortedArrayByField(opcodes, 'number'),
1819
mempools: [],
1920
deployedContracts: sortedArrayByFields(deployedContracts, ['kind', 'name']),
21+
executionNodes,
22+
consensusNodes,
2023
};

src/chains/optimism/nodes.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { Language, Node, NodeType } from '@/types';
2+
import { nethermind, reth } from '../mainnet/nodes/execution';
3+
4+
// Execution nodes.
5+
const opGeth: Node = {
6+
name: 'op-geth',
7+
description:
8+
'Official Golang execution layer implementation of the Ethereum protocol. It implements the Execution-Layer, with minimal changes for a secure Ethereum-equivalent application environment.',
9+
type: NodeType.Execution,
10+
language: Language.Go,
11+
forkOf: 'geth',
12+
repository: 'https://github.com/ethereum-optimism/op-geth',
13+
documentation: 'https://op-geth.optimism.io/',
14+
};
15+
16+
const opErigon: Node = {
17+
name: 'op-erigon',
18+
description: 'Optimism implementation on the efficiency frontier',
19+
type: NodeType.Execution,
20+
language: Language.Go,
21+
forkOf: 'erigon',
22+
repository: 'https://github.com/testinprod-io/op-erigon',
23+
documentation: 'https://op-erigon.testinprod.io/',
24+
};
25+
26+
export const executionNodes: Node[] = [opGeth, opErigon, reth, nethermind];
27+
export const consensusNodes: Node[] = [];

src/components/diff/DiffNodes.tsx

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import { RenderDiff } from '@/components/diff/utils/RenderDiff';
2+
import { Copyable } from '@/components/ui/Copyable';
3+
import { Language, Node, NodeType, SyncStrategy } from '@/types';
4+
import { Collapsible } from './utils/Collapsible';
5+
import { Markdown } from './utils/Markdown';
6+
7+
type Props = {
8+
base: Node[];
9+
target: Node[];
10+
onlyShowDiff: boolean;
11+
};
12+
13+
export const DiffNodes = ({ base, target, onlyShowDiff }: Props) => {
14+
const sortedNodeNames = [...base.map((n) => n.name), ...target.map((n) => n.name)].sort((a, b) =>
15+
a.localeCompare(b)
16+
);
17+
const nodeNames = [...new Set(sortedNodeNames)];
18+
19+
const diffContent = (
20+
<>
21+
{nodeNames.map((name) => {
22+
const baseNode = base.find((n) => n.name === name);
23+
const targetNode = target.find((n) => n.name === name);
24+
if (!baseNode && !targetNode) {
25+
return <></>;
26+
}
27+
28+
const isEqual = JSON.stringify(baseNode) === JSON.stringify(targetNode);
29+
const showNode = !isEqual || !onlyShowDiff;
30+
31+
return (
32+
showNode && (
33+
<div
34+
key={name}
35+
className='grid grid-cols-12 items-center border-b border-zinc-500/10 py-6 dark:border-zinc-500/20'
36+
>
37+
<div className='col-span-2'>
38+
<Copyable content={name} />
39+
</div>
40+
<div className='col-span-5 pr-4'>{formatNode(baseNode)}</div>
41+
<div className='col-span-5'>{formatNode(targetNode)}</div>
42+
</div>
43+
)
44+
);
45+
})}
46+
</>
47+
);
48+
49+
return <RenderDiff content={diffContent} />;
50+
};
51+
52+
const formatNode = (node: Node | undefined) => {
53+
if (!node) return <div>Not present</div>;
54+
return (
55+
<>
56+
<Markdown codeSize='0.9rem' content={node.name} />
57+
<div className='text-secondary text-sm'>
58+
<Markdown content={node.description} />
59+
</div>
60+
<div className='text-secondary mt-3 grid grid-cols-4 space-y-1 text-sm'>
61+
{node.forkOf && (
62+
<>
63+
<div className='col-span-2'>Fork of</div>
64+
<div className='col-span-2'>{node.forkOf}</div>
65+
</>
66+
)}
67+
<div className='col-span-2'>Language</div>
68+
<div className='col-span-2'>{formatLanguage(node.language)}</div>
69+
{node.type == NodeType.Execution && node.syncStrategy && formatSyncStrategies(node)}
70+
</div>
71+
<div className='mt-4'>
72+
<Collapsible
73+
kind='references'
74+
contents={[`[Repository](${node.repository})`, `[Documentation](${node.documentation})`]}
75+
/>
76+
</div>
77+
</>
78+
);
79+
};
80+
81+
const formatLanguage = (l: Language) => {
82+
if (l === Language.Java) return 'Java';
83+
if (l === Language.Go) return 'Go';
84+
if (l === Language.CSharp) return 'CSharp';
85+
if (l === Language.Rust) return 'Rust';
86+
if (l === Language.TypeScript) return 'TypeScript';
87+
if (l === Language.Nim) return 'Nim';
88+
};
89+
90+
const formatSyncStrategies = (n: Node) => {
91+
return (
92+
<>
93+
<div className='col-span-2'>Sync Strategies</div>
94+
<div className='col-span-2'>
95+
{n.syncStrategy && n.syncStrategy.map((s) => formatSyncStrategy(s)!).join(', ')}
96+
</div>
97+
</>
98+
);
99+
};
100+
101+
const formatSyncStrategy = (s: SyncStrategy) => {
102+
if (s === SyncStrategy.Snap) return 'Snap';
103+
if (s === SyncStrategy.Full) return 'Full';
104+
if (s === SyncStrategy.Fast) return 'Fast';
105+
};

src/pages/diff.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { DiffAccountTypes } from '@/components/diff/DiffAccountTypes';
77
import { DiffDeployedContracts } from '@/components/diff/DiffDeployedContracts';
88
import { DiffMempools } from '@/components/diff/DiffMempools';
99
import { DiffMetadata } from '@/components/diff/DiffMetadata';
10+
import { DiffNodes } from '@/components/diff/DiffNodes';
1011
import { DiffOpcodes } from '@/components/diff/DiffOpcodes';
1112
import { DiffPrecompiles } from '@/components/diff/DiffPrecompiles';
1213
import { DiffPredeploys } from '@/components/diff/DiffPredeploys';
@@ -38,6 +39,8 @@ const SECTION_MAP: Record<string, Section> = {
3839
opcodes: { title: 'Opcodes', component: DiffOpcodes },
3940
mempools: { title: 'Mempools', component: DiffMempools },
4041
deployedContracts: { title: 'Deployed Contracts', component: DiffDeployedContracts },
42+
executionNodes: { title: 'Execution Nodes', component: DiffNodes },
43+
consensusNodes: { title: 'Consensus Nodes', component: DiffNodes },
4144
};
4245

4346
const Diff = () => {

src/types/chain.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Chain as Metadata } from '@wagmi/chains';
22
import { AccountType } from './accountType';
33
import { DeployedContract } from './deployedContract';
44
import { Mempool } from './mempool';
5+
import { Node } from './node';
56
import { Opcode } from './opcode';
67
import { Precompile } from './precompile';
78
import { Predeploy } from './predeploy';
@@ -16,4 +17,6 @@ export type Chain = {
1617
opcodes: Partial<Opcode>[];
1718
mempools: Mempool[];
1819
deployedContracts: DeployedContract[];
20+
executionNodes: Node[];
21+
consensusNodes: Node[];
1922
};

0 commit comments

Comments
 (0)