Skip to content

Commit

Permalink
feat: add execution and consensus nodes (#49)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
leovct and mds1 authored Jan 11, 2024
1 parent a6f9235 commit 7a20c96
Show file tree
Hide file tree
Showing 12 changed files with 308 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/chains/arbitrum/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { sortedArrayByField, sortedArrayByFields } from '@/lib/utils';
import { Chain } from '@/types';
import { accountTypes } from './accountTypes';
import { deployedContracts } from './deployedContracts';
import { consensusNodes, executionNodes } from './nodes';
import { signatureTypes } from './signatureTypes';
import { opcodes } from './vm/opcodes';
import { precompiles } from './vm/precompiles';
Expand All @@ -17,4 +18,6 @@ export const arbitrum: Chain = {
opcodes: sortedArrayByField(opcodes, 'number'),
mempools: [],
deployedContracts: sortedArrayByFields(deployedContracts, ['kind', 'name']),
executionNodes,
consensusNodes,
};
14 changes: 14 additions & 0 deletions src/chains/arbitrum/nodes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Language, Node, NodeType } from '@/types';

const nitro: Node = {
name: 'nitro',
description:
'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.',
type: NodeType.Execution,
language: Language.Go,
repository: 'https://github.com/OffchainLabs/nitro',
documentation: 'https://docs.arbitrum.io/',
};

export const executionNodes: Node[] = [nitro];
export const consensusNodes: Node[] = []; // Arbitrum does not have any consensus nodes.
4 changes: 4 additions & 0 deletions src/chains/mainnet/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { Chain } from '@/types';
import { accountTypes } from './accountTypes';
import { deployedContracts } from './deployedContracts';
import { mempools } from './mempools';
import { consensusNodes } from './nodes/consensus';
import { executionNodes } from './nodes/execution';
import { signatureTypes } from './signatureTypes';
import { opcodes } from './vm/opcodes';
import { precompiles } from './vm/precompiles';
Expand All @@ -18,4 +20,6 @@ export const mainnet: Chain = {
opcodes: sortedArrayByField(opcodes, 'number'),
mempools: sortedArrayByField(mempools, 'name'),
deployedContracts: sortedArrayByFields(deployedContracts, ['kind', 'name']),
executionNodes,
consensusNodes,
};
48 changes: 48 additions & 0 deletions src/chains/mainnet/nodes/consensus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Language, Node, NodeType } from '@/types';

const lighthouse: Node = {
name: 'lighthouse',
description: 'Ethereum consensus client in Rust.',
type: NodeType.Consensus,
language: Language.Rust,
repository: 'https://github.com/sigp/lighthouse',
documentation: 'https://lighthouse-book.sigmaprime.io/',
};

const lodestar: Node = {
name: 'lodestar',
description: 'TypeScript Implementation of Ethereum Consensus.',
type: NodeType.Consensus,
language: Language.TypeScript,
repository: 'https://github.com/ChainSafe/lodestar',
documentation: 'https://lodestar.chainsafe.io/',
};

const nimbus: Node = {
name: 'nimbus',
description: 'Nim implementation of the Ethereum Beacon Chain.',
type: NodeType.Consensus,
language: Language.Nim,
repository: 'https://github.com/status-im/nimbus-eth2',
documentation: 'https://nimbus.guide/',
};

const prysm: Node = {
name: 'prysm',
description: 'Go implementation of Ethereum proof of stake.',
type: NodeType.Consensus,
language: Language.Go,
repository: 'https://github.com/prysmaticlabs/prysm',
documentation: 'https://prysmaticlabs.com/',
};

const teku: Node = {
name: 'teku',
description: 'Java Implementation of the Ethereum 2.0 Beacon Chain.',
type: NodeType.Consensus,
language: Language.Java,
repository: 'https://github.com/Consensys/teku',
documentation: 'https://docs.teku.consensys.io/',
};

export const consensusNodes: Node[] = [lighthouse, lodestar, nimbus, prysm, teku];
66 changes: 66 additions & 0 deletions src/chains/mainnet/nodes/execution.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Language, Node, NodeType, SyncStrategy } from '@/types';

const besu: Node = {
name: 'besu',
description: 'An enterprise-grade Java-based, Apache 2.0 licensed Ethereum client.',
type: NodeType.Execution,
language: Language.Java,
syncStrategy: [SyncStrategy.Snap, SyncStrategy.Fast, SyncStrategy.Full],
repository: 'https://github.com/hyperledger/besu',
documentation: 'https://besu.hyperledger.org/',
};

const coregeth: Node = {
name: 'core-geth',
description: 'A highly configurable Go implementation of the Ethereum protocol.',
type: NodeType.Execution,
language: Language.Go,
syncStrategy: [SyncStrategy.Snap, SyncStrategy.Full],
forkOf: 'geth',
repository: 'https://github.com/etclabscore/core-geth',
documentation: 'https://etclabscore.github.io/core-geth/',
};

const erigon: Node = {
name: 'erigon',
description: 'Ethereum implementation on the efficiency frontier.',
type: NodeType.Execution,
language: Language.Go,
syncStrategy: [SyncStrategy.Full],
forkOf: 'geth',
repository: 'https://github.com/ledgerwatch/erigon',
documentation: 'https://erigon.gitbook.io/erigon/',
};

const geth: Node = {
name: 'geth',
description: 'Official Go implementation of the Ethereum protocol.',
type: NodeType.Execution,
language: Language.Go,
syncStrategy: [SyncStrategy.Snap, SyncStrategy.Full],
repository: 'https://github.com/ethereum/go-ethereum',
documentation: 'https://geth.ethereum.org/',
};

export const nethermind: Node = {
name: 'nethermind',
description: 'A robust execution client for Ethereum node operators.',
type: NodeType.Execution,
language: Language.CSharp,
syncStrategy: [SyncStrategy.Snap, SyncStrategy.Fast, SyncStrategy.Full],
repository: 'https://github.com/NethermindEth/nethermind',
documentation: 'https://docs.nethermind.io/',
};

export const reth: Node = {
name: 'reth',
description:
'Modular, contributor-friendly and blazing-fast implementation of the Ethereum protocol, in Rust.',
type: NodeType.Execution,
language: Language.Rust,
syncStrategy: [SyncStrategy.Full],
repository: 'https://github.com/paradigmxyz/reth',
documentation: 'https://paradigmxyz.github.io/reth/',
};

export const executionNodes: Node[] = [besu, coregeth, erigon, geth, nethermind, reth];
3 changes: 3 additions & 0 deletions src/chains/optimism/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { sortedArrayByField, sortedArrayByFields } from '@/lib/utils';
import { Chain } from '@/types';
import { accountTypes } from './accountTypes';
import { deployedContracts } from './deployedContracts';
import { consensusNodes, executionNodes } from './nodes';
import { signatureTypes } from './signatureTypes';
import { opcodes } from './vm/opcodes';
import { precompiles } from './vm/precompiles';
Expand All @@ -17,4 +18,6 @@ export const optimism: Chain = {
opcodes: sortedArrayByField(opcodes, 'number'),
mempools: [],
deployedContracts: sortedArrayByFields(deployedContracts, ['kind', 'name']),
executionNodes,
consensusNodes,
};
27 changes: 27 additions & 0 deletions src/chains/optimism/nodes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Language, Node, NodeType } from '@/types';
import { nethermind, reth } from '../mainnet/nodes/execution';

// Execution nodes.
const opGeth: Node = {
name: 'op-geth',
description:
'Official Golang execution layer implementation of the Ethereum protocol. It implements the Execution-Layer, with minimal changes for a secure Ethereum-equivalent application environment.',
type: NodeType.Execution,
language: Language.Go,
forkOf: 'geth',
repository: 'https://github.com/ethereum-optimism/op-geth',
documentation: 'https://op-geth.optimism.io/',
};

const opErigon: Node = {
name: 'op-erigon',
description: 'Optimism implementation on the efficiency frontier',
type: NodeType.Execution,
language: Language.Go,
forkOf: 'erigon',
repository: 'https://github.com/testinprod-io/op-erigon',
documentation: 'https://op-erigon.testinprod.io/',
};

export const executionNodes: Node[] = [opGeth, opErigon, reth, nethermind];
export const consensusNodes: Node[] = [];
105 changes: 105 additions & 0 deletions src/components/diff/DiffNodes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { RenderDiff } from '@/components/diff/utils/RenderDiff';
import { Copyable } from '@/components/ui/Copyable';
import { Language, Node, NodeType, SyncStrategy } from '@/types';
import { Collapsible } from './utils/Collapsible';
import { Markdown } from './utils/Markdown';

type Props = {
base: Node[];
target: Node[];
onlyShowDiff: boolean;
};

export const DiffNodes = ({ base, target, onlyShowDiff }: Props) => {
const sortedNodeNames = [...base.map((n) => n.name), ...target.map((n) => n.name)].sort((a, b) =>
a.localeCompare(b)
);
const nodeNames = [...new Set(sortedNodeNames)];

const diffContent = (
<>
{nodeNames.map((name) => {
const baseNode = base.find((n) => n.name === name);
const targetNode = target.find((n) => n.name === name);
if (!baseNode && !targetNode) {
return <></>;
}

const isEqual = JSON.stringify(baseNode) === JSON.stringify(targetNode);
const showNode = !isEqual || !onlyShowDiff;

return (
showNode && (
<div
key={name}
className='grid grid-cols-12 items-center border-b border-zinc-500/10 py-6 dark:border-zinc-500/20'
>
<div className='col-span-2'>
<Copyable content={name} />
</div>
<div className='col-span-5 pr-4'>{formatNode(baseNode)}</div>
<div className='col-span-5'>{formatNode(targetNode)}</div>
</div>
)
);
})}
</>
);

return <RenderDiff content={diffContent} />;
};

const formatNode = (node: Node | undefined) => {
if (!node) return <div>Not present</div>;
return (
<>
<Markdown codeSize='0.9rem' content={node.name} />
<div className='text-secondary text-sm'>
<Markdown content={node.description} />
</div>
<div className='text-secondary mt-3 grid grid-cols-4 space-y-1 text-sm'>
{node.forkOf && (
<>
<div className='col-span-2'>Fork of</div>
<div className='col-span-2'>{node.forkOf}</div>
</>
)}
<div className='col-span-2'>Language</div>
<div className='col-span-2'>{formatLanguage(node.language)}</div>
{node.type == NodeType.Execution && node.syncStrategy && formatSyncStrategies(node)}
</div>
<div className='mt-4'>
<Collapsible
kind='references'
contents={[`[Repository](${node.repository})`, `[Documentation](${node.documentation})`]}
/>
</div>
</>
);
};

const formatLanguage = (l: Language) => {
if (l === Language.Java) return 'Java';
if (l === Language.Go) return 'Go';
if (l === Language.CSharp) return 'CSharp';
if (l === Language.Rust) return 'Rust';
if (l === Language.TypeScript) return 'TypeScript';
if (l === Language.Nim) return 'Nim';
};

const formatSyncStrategies = (n: Node) => {
return (
<>
<div className='col-span-2'>Sync Strategies</div>
<div className='col-span-2'>
{n.syncStrategy && n.syncStrategy.map((s) => formatSyncStrategy(s)!).join(', ')}
</div>
</>
);
};

const formatSyncStrategy = (s: SyncStrategy) => {
if (s === SyncStrategy.Snap) return 'Snap';
if (s === SyncStrategy.Full) return 'Full';
if (s === SyncStrategy.Fast) return 'Fast';
};
3 changes: 3 additions & 0 deletions src/pages/diff.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { DiffAccountTypes } from '@/components/diff/DiffAccountTypes';
import { DiffDeployedContracts } from '@/components/diff/DiffDeployedContracts';
import { DiffMempools } from '@/components/diff/DiffMempools';
import { DiffMetadata } from '@/components/diff/DiffMetadata';
import { DiffNodes } from '@/components/diff/DiffNodes';
import { DiffOpcodes } from '@/components/diff/DiffOpcodes';
import { DiffPrecompiles } from '@/components/diff/DiffPrecompiles';
import { DiffPredeploys } from '@/components/diff/DiffPredeploys';
Expand Down Expand Up @@ -38,6 +39,8 @@ const SECTION_MAP: Record<string, Section> = {
opcodes: { title: 'Opcodes', component: DiffOpcodes },
mempools: { title: 'Mempools', component: DiffMempools },
deployedContracts: { title: 'Deployed Contracts', component: DiffDeployedContracts },
executionNodes: { title: 'Execution Nodes', component: DiffNodes },
consensusNodes: { title: 'Consensus Nodes', component: DiffNodes },
};

const Diff = () => {
Expand Down
3 changes: 3 additions & 0 deletions src/types/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Chain as Metadata } from '@wagmi/chains';
import { AccountType } from './accountType';
import { DeployedContract } from './deployedContract';
import { Mempool } from './mempool';
import { Node } from './node';
import { Opcode } from './opcode';
import { Precompile } from './precompile';
import { Predeploy } from './predeploy';
Expand All @@ -16,4 +17,6 @@ export type Chain = {
opcodes: Partial<Opcode>[];
mempools: Mempool[];
deployedContracts: DeployedContract[];
executionNodes: Node[];
consensusNodes: Node[];
};
2 changes: 2 additions & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ export type {
ProxiedDeployedContract,
} from './deployedContract';
export { DeployedContractKind } from './deployedContract';
export type { Node } from './node';
export { NodeType, Language, SyncStrategy } from './node';
30 changes: 30 additions & 0 deletions src/types/node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export type Node = {
name: string;
description: string;
type: NodeType;
language: Language;
syncStrategy?: SyncStrategy[]; // only for execution nodes.
forkOf?: string;
repository: string;
documentation: string;
};

export enum NodeType {
Execution,
Consensus,
}

export enum Language {
Java,
Go,
CSharp,
Rust,
TypeScript,
Nim,
}

export enum SyncStrategy {
Snap,
Fast,
Full,
}

1 comment on commit 7a20c96

@vercel
Copy link

@vercel vercel bot commented on 7a20c96 Jan 11, 2024

Choose a reason for hiding this comment

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

Please sign in to comment.