Client principal d'Ethereum : architecture générale de Geth

Cet article est le premier d'une série sur le code source de Geth. Grâce à cette série, nous allons établir un cadre pour étudier la mise en œuvre de Geth, permettant aux développeurs d'approfondir les parties qui les intéressent. Cette série comprend six articles, et dans le premier article, nous examinerons l'architecture de conception du client Geth au niveau d'exécution ainsi que le processus de démarrage du nœud Geth. La vitesse de mise à jour du code Geth est très rapide, le code que vous verrez par la suite peut être différent, mais l'architecture générale reste essentiellement la même, et le nouveau code peut également être lu avec la même approche.

01\Client Ethereum

Avant la mise à niveau The Merge, Ethereum avait un seul client, qui était responsable de l'exécution des transactions et aussi de la consensus de la blockchain, garantissant que la blockchain produisait de nouveaux blocs dans un certain ordre. Après la mise à niveau The Merge, le client Ethereum a été divisé en couche d'exécution et couche de consensus. La couche d'exécution est responsable de l'exécution des transactions, de l'état et de la maintenance des données, tandis que la couche de consensus est responsable de l'implémentation des fonctionnalités de consensus. La couche d'exécution et la couche de consensus communiquent via une API. Chaque couche a ses propres spécifications, et les clients peuvent être implémentés dans différentes langues, mais doivent respecter les spécifications correspondantes, parmi lesquelles Geth est une implémentation d'un client de couche d'exécution. Les clients de couche d'exécution et de couche de consensus les plus courants ont les implémentations suivantes :

Couche d’exécution

  • Geth : maintenu par une équipe directement financée par la Fondation Ethereum, développé en Go, est reconnu comme le client le plus stable et éprouvé.
  • Nethermind : Développé et maintenu par l'équipe de Nethermind, utilisant le langage C#, a été initialement financé par la Fondation Ethereum et la communauté Gitcoin.
  • Besu : initialement développé par l'équipe PegaSys de ConsenSys, maintenant un projet de la communauté Hyperledger, développé en Java.
  • Erigon : Développé et maintenu par l'équipe Erigon, financé par la Fondation Ethereum et BNB Chain. Dérivé de Geth en 2017, son objectif est d'améliorer la vitesse de synchronisation et l'efficacité du disque.
  • Reth : développé sous la direction de Paradigm, le langage de développement est Rust, mettant l'accent sur la modularité et la haute performance, il est maintenant proche de la maturité et peut être utilisé en environnement de production.

Couche de consensus

  • Prysm : Maintenu par Prysmatic Labs, c'est l'un des premiers clients de couche de consensus d'Ethereum, développé en langage Go, axé sur l'utilisabilité et la sécurité, financé dès le début par la fondation Ethereum.
  • Lighthouse : maintenu par l'équipe Sigma Prime, développé en langage Rust, axé sur la haute performance et la sécurité de niveau entreprise, adapté aux scénarios à forte charge.
  • Teku : développé à l'origine par l'équipe PegaSys de ConsenSys, il est ensuite devenu une partie de la communauté Hyperledger Besu, développé en langage Java.
  • Nimbus : développé et maintenu par l'équipe de Status Network, développé en langage Nim, optimisé pour les appareils à ressources limitées (comme les smartphones et les appareils IoT), visant à réaliser un fonctionnement léger dans les systèmes embarqués.

02\Présentation de la couche d'exécution

On peut considérer la couche d'exécution d'Ethereum comme une machine à états pilotée par des transactions, la fonction de base de la couche d'exécution est de mettre à jour les données d'état en exécutant des transactions via l'EVM. En plus de l'exécution des transactions, il existe également des fonctions telles que la sauvegarde et la vérification des blocs et des données d'état, l'exécution d'un réseau p2p et la maintenance d'un pool de transactions.

Les transactions sont générées par les utilisateurs (ou des programmes) selon le format défini par les spécifications de la couche d'exécution d'Ethereum. Les utilisateurs doivent signer la transaction, et si la transaction est valide (Nonce consécutif, signature correcte, frais de gaz suffisants, logique métier correcte), alors la transaction sera finalement exécutée par l'EVM, mettant ainsi à jour l'état du réseau Ethereum. L'état ici fait référence à un ensemble de structures de données, de données et de bases de données, y compris les adresses de comptes externes, les adresses de contrats, les soldes d'adresses ainsi que le code et les données.

La couche d'exécution est responsable de l'exécution des transactions et de la maintenance de l'état après l'exécution des transactions, tandis que la couche de consensus est responsable de la sélection des transactions à exécuter. L'EVM est la fonction de transition d'état dans cette machine d'état, dont les entrées peuvent provenir de plusieurs sources, y compris les informations sur le dernier bloc fournies par la couche de consensus ou les blocs téléchargés depuis le réseau p2p.

La couche de consensus et la couche d'exécution communiquent via l'API Engine, qui est le seul moyen de communication entre la couche d'exécution et la couche de consensus. Si la couche de consensus obtient le droit de produire des blocs, elle le fera via l'API Engine pour permettre à la couche d'exécution de générer de nouveaux blocs. Si elle n'obtient pas le droit de produire des blocs, elle synchronisera les derniers blocs pour que la couche d'exécution puisse les vérifier et les exécuter, maintenant ainsi le consensus avec l'ensemble du réseau Ethereum.

La couche d'exécution peut être logiquement divisée en 6 parties :

  • EVM : est responsable de l’exécution des transactions, et l’exécution des transactions est également le seul moyen de modifier le nombre d’états
  • Stockage : responsable du stockage des données d'état et des blocs, etc.
  • Piscine de transactions : utilisée pour les transactions soumises par les utilisateurs, stockées temporairement et diffusées entre différents nœuds via un réseau p2p.
  • réseau p2p : utilisé pour découvrir des nœuds, synchroniser des transactions, télécharger des blocs, etc.
  • Services RPC : fournissent la capacité d'accéder aux nœuds, par exemple, les utilisateurs envoient des transactions aux nœuds, l'interaction entre la couche de consensus et la couche d'exécution.
  • BlockChain : responsable de la gestion des données de la blockchain Ethereum

La figure ci-dessous montre les processus clés de la couche d'exécution, ainsi que les fonctions de chaque partie :

Clients principaux d'Ethereum : architecture générale de Geth

Pour la couche d'exécution (ici, nous ne discutons temporairement que des Nœuds complets), il y a trois processus clés :

  • Si vous êtes un nouveau nœud rejoignant Ethereum, vous devez synchroniser les blocs et les données d'état à partir d'autres nœuds via le réseau p2p. Si vous effectuez une synchronisation complète, vous téléchargerez les blocs un par un à partir du bloc de genèse, validerez les blocs et reconstruirez la base de données d'état via l'EVM. Si vous effectuez une synchronisation instantanée, vous passerez tout le processus de validation des blocs et téléchargerez directement les données d'état du dernier point de contrôle et les blocs suivants.
  • Si c'est un nœud déjà synchronisé à l'état le plus récent, il continuera à récupérer les derniers blocs produits via l'API Engine depuis la couche de consensus, à valider les blocs, puis à exécuter toutes les transactions dans les blocs via l'EVM pour mettre à jour la base de données d'état et à écrire les blocs dans la chaîne locale.
  • Si le nœud est déjà synchronisé à l'état le plus récent et que le nœud a obtenu le droit de produire des blocs dans la couche de consensus, il générera le dernier bloc via l'API Engine, la couche d'exécution récupérera les transactions depuis le pool de transactions et les exécutera, puis assemblera le tout en un bloc qui sera transmis à la couche de consensus via l'API Engine, et la couche de consensus diffusera le bloc sur le réseau p2p de la couche de consensus.

03\Structure du code source

La structure du code de go-ethereum est très vaste, mais de nombreux codes appartiennent à des codes auxiliaires et à des tests unitaires. Lors de l'étude du code source de Geth, il suffit de se concentrer sur l'implémentation principale du protocole. Les fonctionnalités des différents modules sont les suivantes. Il est important de se concentrer sur les modules core, eth, ethdb, node, p2p, rlp, trie & triedb.

  • comptes : gérer les comptes Ethereum, y compris la génération de paires de clés publiques et privées, la vérification de signature, la dérivation d'adresses, etc.
  • beacon : traite la logique d'interaction avec la chaîne de balises Ethereum (Beacon Chain), prenant en charge les fonctionnalités après la fusion (The Merge) du consensus de preuve d'enjeu (PoS)
  • build : scripts de construction et configurations de compilation (comme Dockerfile, support de compilation multiplateforme)
  • cmd : point d'entrée de l'outil de ligne de commande, contenant plusieurs sous-commandes
  • commun : Outils génériques, tels que le traitement des octets, la conversion de format d'adresse, les fonctions mathématiques
  • consensus : définition du moteur de consensus, y compris l'ancienne preuve de travail (Ethash) et la preuve d'enjeu en solo (Clique) ainsi que le moteur Beacon, etc.
  • console : fournit une console JavaScript interactive, permettant aux utilisateurs d'interagir directement avec le nœud Ethereum via la ligne de commande (comme appeler l'API Web3, gérer des comptes, interroger des données de blockchain)
  • core : logique centrale de la blockchain, gérant le cycle de vie des blocs/transactions, la machine à états, le calcul du Gas, etc.
  • crypto : mise en œuvre des algorithmes de chiffrement, y compris la courbe elliptique (secp256k1), le hachage (Keccak-256), la vérification de signature
  • docs : documents (comme les spécifications de conception, les explications API)
  • eth : mise en œuvre complète du protocole du réseau Ethereum, y compris les services de nœud, la synchronisation des blocs (comme la synchronisation rapide, le mode d'archivage), la diffusion des transactions, etc.
  • ethclient : bibliothèque cliente Ethereum, encapsulant l'interface JSON-RPC, permettant aux développeurs Go d'interagir avec les nœuds Ethereum (comme interroger des blocs, envoyer des transactions, déployer des contrats)
  • ethdb : couche d’abstraction de base de données, supportant LevelDB, Pebble, base de données en mémoire, etc., stockant les données de la blockchain (blocs, état, transactions)
  • ethstats : collecte et signale l’état de fonctionnement des nœuds au service de statistiques pour surveiller l’état de santé du réseau
  • événement : mettre en œuvre un mécanisme d'abonnement et de publication d'événements, supportant la communication asynchrone entre les modules internes du nœud (comme l'arrivée de nouveaux blocs, la mise à jour du pool des transactions)
  • graphql : fournit une interface GraphQL, supportant des requêtes complexes (remplaçant certaines fonctionnalités JSON-RPC)
  • interne : outils internes ou code limitant l'accès externe
  • log : système de journalisation, prend en charge la sortie de journaux de niveau, enregistrement de journaux de contexte
  • métriques : collecte des indicateurs de performance (prise en charge de Prometheus)
  • mineur : logique liée à l'exploitation minière, génération de nouveaux blocs et regroupement des transactions (dans le cadre de PoW)
  • nœud : gestion des services de nœud, intégration du démarrage et de la configuration des modules p2p, RPC, base de données, etc.
  • p2p : protocole de réseau pair à pair, prend en charge la découverte de nœuds, le transfert de données et la communication chiffrée.
  • params : définit les paramètres du réseau Ethereum (réseau principal, réseau de test, configuration du bloc de genèse)
  • rlp : mise en œuvre du protocole de sérialisation de données spécifique à Ethereum RLP (Recursive Length Prefix), utilisé pour l'encodage/décodage des blocs, transactions et autres structures de données.
  • rpc : implémenter l'interface JSON-RPC et IPC, permettant aux programmes externes d'interagir avec le Nœud
  • signataire : gestion des signatures de transaction (intégration de portefeuille matériel)
  • tests : tests d'intégration et tests d'état, vérification de la compatibilité des protocoles
  • trie & triedb : mise en œuvre de l'arbre de Merkle Patricia (Merkle Patricia Trie) pour le stockage et la gestion efficaces de l'état des comptes et du stockage des contrats.

04\Division des modules de la couche d'exécution

L'accès externe au nœud Geth se fait de deux manières, l'une par RPC et l'autre par Console. Le RPC est adapté aux utilisateurs externes, tandis que la Console est destinée aux administrateurs du nœud. Mais que ce soit par RPC ou Console, il s'agit d'utiliser des capacités déjà encapsulées en interne, qui sont construites de manière hiérarchique.

La couche extérieure est constituée des capacités de l'API utilisées pour accéder aux nœuds externes. L'Engine API est utilisé pour la communication entre la couche d'exécution et la couche de consensus, l'Eth API est utilisé pour que les utilisateurs externes ou les programmes envoient des transactions et obtiennent des informations sur les blocs, et le Net API est utilisé pour obtenir l'état du réseau p2p, etc. Par exemple, si un utilisateur envoie une transaction via l'API, cette transaction sera finalement soumise au pool de transactions, qui gère les transactions. De plus, si un utilisateur a besoin d'obtenir des données sur un bloc, il devra appeler les capacités de la base de données pour récupérer le bloc correspondant.

Au niveau suivant de l'API se trouve la mise en œuvre des fonctionnalités centrales, y compris le pool de transactions, le regroupement des transactions, la production de blocs, la synchronisation des blocs et des états, etc. Ces fonctionnalités dépendent alors de capacités de niveau inférieur, par exemple, le pool de transactions, ainsi que la synchronisation des blocs et des états nécessitent les capacités du réseau p2p. La production de blocs et la synchronisation des blocs provenant d'autres nœuds doivent être vérifiées avant d'être écrites dans la base de données locale, ce qui nécessite des capacités de l'EVM et du stockage des données.

! Client principal d’Ethereum : architecture globale de Geth

Structure de données centrale de la couche d'exécution

Ethereum

La structure Ethereum dans eth/backend.go est une abstraction de l’ensemble du protocole Ethereum, qui comprend essentiellement les principaux composants d’Ethereum, à l’exception de l’EVM, qui est instancié chaque fois qu’une transaction est traitée, et n’a pas besoin d’être initialisé avec le nœud entier.

type Ethereum struct { // Configuration d’Ethereum, y compris la configuration de la chaîne *ethconfig. Config // Pool de transactions, une fois la transaction de l’utilisateur soumise, accédez au pool de transactions txPool *txpool. TxPool // Utilisé pour suivre et gérer les transactions locales localTxTracker *locals. TxTracker // Structure de la blockchain blockchain *core. BlockChain // est le composant central de la couche réseau du nœud Ethereum, responsable de la gestion de toutes les communications avec les autres nœuds, y compris la synchronisation des blocs, la diffusion et la réception des transactions, ainsi que la gestion du gestionnaire de connexion des nœuds homologues // responsable de la découverte des nœuds et de la gestion des sources des nœuds discmix *enode. FairMix // Responsable du stockage persistant de la chaîne de données blockchainDb ethdb. Base de données // Responsable de la publication et de l’abonnement de divers événements internes à eventMux *event. TypeMux // Consensus du moteur. Moteur // Gérer les comptes utilisateurs et les clés accountManager *comptes. Manager // Gérer les filtres de journaux et les filterMaps de chunk *filtermaps. FilterMaps // Canal pour arrêter filterMaps en toute sécurité, en s’assurant que les ressources sont nettoyées correctement lorsque les nœuds sont arrêtés closeFilterMaps chan chan struct{} // Fournir un support backend pour l’API RPC APIBackend *EthAPIBackend // Sous PoS, travaillez avec le moteur de consensus pour valider le mineur de blocs *miner. Miner // Le prix de gaz le plus bas accepté par le nœud est gasPrice *big. Int // ID réseau networkID uint64 // Fournit des services RPC liés au réseau, permettant d’interroger l’état du réseau via RPC netRPCService *ethapi. NetAPI // Gérez les connexions réseau P2P, gérez la découverte des nœuds et l’établissement des connexions, et fournissez des fonctions de transport réseau sous-jacentes p2pServer *p2p. Serveur // Protégez l’accès simultané à la synchronisation des verrous de champs mutables. RWMutex // Suit si le nœud est en panne correctement et aide à restaurer shutdownTracker après un arrêt anormal *shutdowncheck. ShutdownTracker }

Nœud

Dans node/node.go, le Nœud est une autre structure de données centrale qui agit comme un conteneur, responsable de la gestion et de la coordination du fonctionnement de divers services. Dans la structure ci-dessous, il faut prêter attention au champ lifecycles, le Lifecycle étant utilisé pour gérer le cycle de vie des fonctionnalités internes. Par exemple, l'abstraction Ethereum ci-dessus nécessite de dépendre du Nœud pour démarrer et s'enregistrer dans les lifecycles. Cela permet de séparer les fonctionnalités concrètes de l'abstraction du nœud, améliorant ainsi l'évolutivité de l'ensemble de l'architecture, ce Nœud devant être distingué de celui du devp2p.

type Node struct { eventmux *event. TypeMux config *Config // Gestionnaire de compte, responsable de la gestion des portefeuilles et des comptes accman *accounts. Journal du gestionnaire. Logger keyDir string keyDirTemp bool dirLock *flock. Flock stop chan struct{} // serveur d’instance réseau p2p *p2p. Démarrage du serveurStopLock synchronisation. Mutex // Suivre l’état du cycle de vie du nœud (initialisé, en cours d’exécution, fermé) état int lock sync. Mutex // Tous les backends, services et cycles de vie des services auxiliaires enregistrés []Lifecycle // Liste des API actuellement disponibles rpcAPIs []rpc. API // Différentes méthodes d’accès pour RPC http *httpServer ws *httpServer httpAuth *httpServer wsAuth *httpServer ipc *ipcServer inprocHandler *rpc. Carte des bases de données du serveur[*closeTrackingDB]struct{} }

Si nous regardons la couche d’exécution d’Ethereum d’un point de vue abstrait, Ethereum, en tant qu’ordinateur mondial, doit inclure trois parties, le réseau, l’informatique et le stockage, alors les composants correspondant à ces trois parties dans la couche d’exécution Ethereum sont :

  • Réseau : devp2p
  • Calcul : EVM
  • Stockage : ethdb

devp2p

Ethereum est essentiellement un système distribué, chaque nœud est connecté aux autres nœuds via un réseau p2p. L'implémentation du protocole de réseau p2p dans Ethereum est devp2p.

devp2p a deux fonctions essentielles, l'une est la découverte de nœuds, permettant aux nœuds de se connecter avec d'autres nœuds lors de leur connexion au réseau ; l'autre est le service de transmission de données, qui permet d'échanger des données après avoir établi un lien avec d'autres nœuds.

Dans le fichier p2p/enode/node.go, la structure Node représente un Nœud dans le réseau p2p, où la structure enr.Record stocke des paires clé-valeur contenant les détails du Nœud, y compris les informations d'identité (l'algorithme de signature utilisé pour l'identité du Nœud, la clé publique), les informations réseau (adresse IP, numéro de port), les informations sur les protocoles pris en charge (comme le support des protocoles eth/68 et snap) et d'autres informations personnalisées. Ces informations sont encodées au moyen de RLP, les spécifications exactes étant définies dans l'eip-778 :

type Node struct { // Enregistrement de noeud contenant diverses propriétés du noeud r enr. Record // Identifiant unique du noeud, 32 octets id ID // nom d’hôte Trace le nom DNS du noeud hostname string // L’adresse IP du noeud ip netip. Addr // UDP port udp uint16 // TCP port tcp uint16 }// enr. Recordtype Record struct { // Numéro de série seq uint64 // Signature de signature []byte // Enregistrement brut encodé RLP []byte // Liste triée de toutes les paires clé-valeur []pair }

La structure Table dans p2p/discover/table.go est la structure de données centrale de l'implémentation du protocole de découverte de nœuds devp2p. Elle met en œuvre une table de hachage distribuée similaire à Kademlia pour maintenir et gérer les informations sur les nœuds dans le réseau.

printf("type Table struct { mutex sync. Mutex // Indexer les compartiments de noeuds connus par distance [nBuckets]*bucket // Pépinière de noeuds d’amorçage []*enode. Node rand reseedingRandom ips netutil. Table de revalidation DistinctNetSetRevalidation // Base de données des noeuds connus db *enode. DB net transport cfg Config log log. Logger // Traite périodiquement divers événements dans le réseau refreshReq chan chan struct{} revalResponseCh chan revalidationResponse addNodeCh chan addNodeOp addNodeHandled chan bool trackRequestCh chan trackRequestOp initDone chan struct{} closeReq chan struct{} closed chan struct{} // Ajouter et supprimer des interfaces pour les noeuds nodeAddedHook func(*bucket, *tableNode) nodeRemovedHook func(*seau, *tableNode)} monde !" );

ethdb

ethdb a terminé l'abstraction du stockage des données Ethereum, fournissant une interface de stockage unifiée. La base de données sous-jacente peut être leveldb, pebble ou d'autres bases de données. Il peut y avoir de nombreuses extensions tant que l'unité est maintenue au niveau de l'interface.

Certaines données (comme les données de bloc) peuvent être lues et écrites directement dans la base de données sous-jacente via l'interface ethdb, tandis que d'autres interfaces de stockage de données sont construites sur la base d'ethdb. Par exemple, une grande partie des données de la base de données est constituée de données d'état, qui sont organisées en structure MPT. Dans Geth, l'implémentation correspondante est le trie. Au cours de l'exécution du nœud, les données trie produisent de nombreux états intermédiaires. Ces données ne peuvent pas être appelées directement par ethdb pour la lecture et l'écriture, elles nécessitent triedb pour gérer ces données et états intermédiaires, et enfin, elles sont persistées via ethdb.

L’interface qui définit les capacités de lecture et d’écriture de la base de données sous-jacente dans ethdb/database.go n’inclut pas d’implémentation spécifique, qui sera implémentée par les différentes bases de données elles-mêmes. Par exemple, leveldb ou les bases de données Pebble. Deux couches d’interfaces de lecture/écriture de données sont définies dans la base de données, parmi lesquelles l’interface KeyValueStore est utilisée pour stocker les données actives et changeant fréquemment, telles que le dernier bloc, l’état, etc. AncientStore est utilisé pour traiter des données historiques, qui changent rarement une fois écrites.

// Interface de niveau supérieur de la base de données type Database interface { KeyValueStore NœudStore} // Interface de lecture/écriture des données KV type KeyValueStore interface { KeyValueReader KeyValueWriter KeyValueStater KeyValueRangeDeleter Batcher Iteratee Compacter io.Closer} // Interface de lecture/écriture pour le traitement des anciennes données type NœudStore interface { AncientReader AncientWriter AncientStater io.Closer}

EVM

EVM est la fonction de transition d'état de la machine d'état d'Ethereum, toutes les mises à jour des données d'état ne peuvent être effectuées que via l'EVM. Le réseau p2p peut recevoir des informations sur les transactions et les blocs, et ces informations, une fois traitées par l'EVM, deviendront une partie de la base de données d'état. L'EVM masque les différences de matériel sous-jacent, permettant aux programmes de s'exécuter sur différentes EVM de plateforme tout en obtenant des résultats cohérents. C'est une approche de conception très mature, le JVM dans le langage Java est également une conception similaire.

L'implémentation de l'EVM se compose de trois composants principaux : la structure EVM définie dans core/vm/evm.go qui définit la structure globale de l'EVM et ses dépendances, y compris le contexte d'exécution, les dépendances de la base de données d'état, etc. ; la structure EVMInterpreter définie dans core/vm/interpreter.go qui définit l'implémentation de l'interpréteur, responsable de l'exécution du bytecode EVM ; la structure Contract dans core/vm/contract.go qui encapsule les paramètres spécifiques de l'appel de contrat, y compris l'appelant, le code du contrat, les entrées, etc., et qui définit dans core/vm/opcodes.go tous les codes d'opération actuels :

EVMtype EVM struct { // Contexte de bloc, contenant des informations relatives aux blocs Context BlockContext // Contexte de transaction, contenant des informations relatives aux transactions TxContext // Base de données d’état, utilisée pour accéder et modifier l’état du compte StateDB StateDB // Profondeur d’appel actuelle int // Paramètre de configuration de la chaîne chainConfig *params. ChainConfig chainRules. Rules // EVM Config Config // Interpréteur de bytecode *EVMInterpreter // Abandon de l’indicateur d’exécution abort atomic. Bool callGasTemp uint64 // précompile map[common. Adresse]PrecompiledContract jumpDests map[common. Hash]bitvec }type EVMInterpreter struct { // Pointer vers l’instance EVM à laquelle il appartient evm *EVM // Table de saut d’opcode *JumpTable // Instance de hasher Keccak256, partager le chiffrement hasher entre les opcodes. KeccakState // Keccak256 hasher hasher common. Hash // S’il s’agit du mode lecture seule, la modification de l’état n’est pas autorisée en mode lecture seule readOnly bool // Les données de retour du dernier CALL sont utilisées pour une réutilisation ultérieure returnData []byte }type Contract struct { // l’adresse de l’appelant est commune. Address // Adresse du contrat : adresse commune. Adresse jumpdests map[common. Analyse de Hash]bitvec bitvec // Code de Bytecode du Contrat []byte // Hachage de code CodeHash commun. Hash // Appelez input []byte // S’il faut déployer IsDeployment bool pour le contrat // S’il faut appeler IsSystemCall bool // Gaz disponible uint64 // La quantité d’ETH attachée à la valeur d’appel *uint256. Int }

Autres modules implémentés

La fonctionnalité de la couche d'exécution est réalisée par une approche par couches, et les autres modules et fonctionnalités sont construits sur la base de ces trois composants principaux. Voici une présentation de quelques modules clés.

Sous eth/protocols, il existe une implémentation des sous-protocoles du réseau p2p actuel d'Ethereum. Il y a les sous-protocoles eth/68 et snap, qui sont tous construits sur devp2p.

eth/68 est le protocole principal d'Ethereum, le nom du protocole est eth, 68 est son numéro de version, puis sur la base de ce protocole, des fonctionnalités telles que le pool de transactions (TxPool), la synchronisation des blocs (Downloader) et la synchronisation des transactions (Fetcher) ont été mises en œuvre. Le protocole snap est utilisé pour synchroniser rapidement les blocs et les données d'état lors de l'ajout de nouveaux nœuds au réseau, ce qui peut considérablement réduire le temps de démarrage des nouveaux nœuds.

ethdb fournit des capacités de lecture et d'écriture pour la base de données sous-jacente. Étant donné qu'il existe de nombreuses structures de données complexes dans le protocole Ethereum, il n'est pas possible de gérer ces données directement via ethdb. C'est pourquoi rawdb et statedb ont été mis en œuvre sur ethdb pour gérer respectivement les données de bloc et d'état.

L'EVM traverse tous les processus principaux, que ce soit la construction de blocs ou la validation de blocs, elle nécessite l'exécution de transactions via l'EVM.

05\Geth Nœud démarrage processus

Le démarrage de Geth se compose de deux phases : la première phase initialise les composants et les ressources nécessaires au démarrage du nœud, la deuxième phase démarre officiellement le nœud, puis fournit des services externes.

Clients principaux d'Ethereum : Architecture globale de Geth

Nœud d'initialisation

Lors du démarrage d'un nœud geth, le code suivant sera impliqué :

Clients principaux d'Ethereum : architecture globale de Geth

L'initialisation des différents modules est comme suit :

  • cmd/geth/main.go : point d'entrée du nœud geth
  • cmd/geth/config.go (makeFullNode) : charger la configuration, initialiser le Nœud
  • nœud/nœud.go : initialiser le conteneur principal du nœud Ethereum
  1. node.rpcstack.go : initialiser le module RPC
  2. accounts.manager.go : initialiser accountManager
  • eth/backend.go : initialiser une instance Ethereum
  1. nœud/node.go OpenDatabaseWithFreezer : initialiser chaindb
  2. eth/ethconfig/config.go : initialiser l'instance du moteur de consensus (ici, le moteur de consensus ne participe pas réellement au consensus, il ne fait que vérifier les résultats de la couche de consensus et traiter les demandes de retrait des validateurs)
  3. core/blockchain.go : initialiser le blockchain
  4. core/filterMaps.go : initialiser filtermaps
  5. core/txpool/blobpool/blobpool.go : initialiser le Nœud de transactions blob
  6. core/txpool/legacypool/legacypool.go : initialiser le pool de transactions ordinaires
  7. cord/txpool/locals/tx_tracker.go : Suivi des transactions local (nécessite une configuration pour activer le suivi des transactions local, les transactions locales seront traitées avec une priorité plus élevée)
  8. eth/handler.go : Initialiser une instance de Handler pour le protocole.
  9. miner/miner.go : module d'instanciation de l'emballage des transactions (ancien module de minage)
  10. eth/api_backend.go : instancier le service RPC
  11. eth/gasprice/gasprice.go : instanciation du service de requête des prix du gaz
  12. internal/ethapi/api.go : instantiation de l'API RPC du réseau P2P
  13. nœud/node.go(EnregistrerAPIs) : enregistrer l'API RPC
  14. nœud/node.go(EnregistrerProtocoles) : enregistrer les Protocoles p2p
  15. nœud/node.go(RegisterLifecycle) : enregistrer le cycle de vie des différents composants
  • cmd/utils/flags.go(EnregistrerFilterAPI):enregistrer l'API RPC de filtre
  • cmd/utils/flags.go(Enregistrer le service GraphQL) : registre API RPC GraphQL (si configuré)
  • cmd/utils/flags.go(Enregistrer le service EthStats) : Enregistrer l'API RPC EthStats (si configurée)
  • eth/catalyst/api.go : Enregistrer l'API Engine

L'initialisation du nœud se fera dans makeFullNode de cmd/geth/config.go, en se concentrant sur l'initialisation des trois modules suivants.

Clients principaux Ethereum : Architecture globale de Geth

Dans la première étape, la structure Node dans node/node.go sera initialisée, c'est le conteneur de tout le nœud, toutes les fonctionnalités doivent fonctionner dans ce conteneur. La deuxième étape consiste à initialiser la structure Ethereum, qui inclut la mise en œuvre de diverses fonctions essentielles d'Ethereum, Ethereum doit également être enregistré dans le Nœud. La troisième étape consiste à enregistrer l'API Engine dans le Nœud.

L'initialisation du Nœud consiste à créer une instance de Nœud, puis à initialiser le serveur p2p, la gestion des comptes et les ports de protocole http exposés à l'extérieur.

Clients principaux d'Ethereum : architecture générale de Geth

Ethereum est beaucoup plus compliqué à initialiser, et la plupart des fonctionnalités de base sont initialisées ici. Tout d’abord, la base de données ethdb sera initialisée et la configuration de la chaîne sera chargée à partir du stockage, puis le moteur de consensus sera créé, où le moteur de consensus n’effectuera pas d’opérations de consensus, mais vérifiera uniquement les résultats renvoyés par la couche de consensus, et si une demande de retrait se produit dans la couche de consensus, l’opération de retrait réelle sera également effectuée ici. Initialisez ensuite la structure de la chaîne de blocs et le pool de transactions.

Une fois que tout cela est terminé, le gestionnaire sera initialisé. Le gestionnaire est le point d'entrée pour le traitement de toutes les requêtes réseau p2p, y compris la synchronisation des transactions, le téléchargement des blocs, etc. C'est un composant clé pour la mise en œuvre d'un fonctionnement décentralisé d'Ethereum. Après que tout cela soit terminé, certains sous-protocoles, tels que eth/68, snap, qui sont réalisés sur la base de devp2p, seront enregistrés dans le conteneur Nœud. Enfin, Ethereum sera enregistré en tant que cycle de vie dans le conteneur Nœud, et l'initialisation d'Ethereum sera terminée.

! Client principal d’Ethereum : architecture globale de Geth

Enfin, l'initialisation de l'API Engine est relativement simple, il suffit d'enregistrer l'API Engine dans le Nœud. À ce stade, l'initialisation du nœud est entièrement terminée.

Nœud de démarrage

Après avoir terminé l'initialisation du nœud, il est nécessaire de démarrer le nœud. Le processus de démarrage du nœud est relativement simple, il suffit de démarrer tous les services RPC et Lifecycle déjà enregistrés, alors tout le nœud peut commencer à fournir des services externes.

Clients principaux d'Ethereum : Architecture générale de Geth

06\Résumé

Avant de comprendre en profondeur la mise en œuvre de la couche d'exécution d'Ethereum, il est nécessaire d'avoir une vue d'ensemble d'Ethereum. On peut considérer Ethereum comme une machine d'état pilotée par des transactions, où la couche d'exécution est responsable de l'exécution des transactions et des changements d'état, tandis que la couche de consensus est chargée de faire fonctionner la couche d'exécution, y compris la production de blocs par la couche d'exécution, la détermination de l'ordre des transactions, le vote sur les blocs et l'obtention de la finalité des blocs. Étant donné que cette machine d'état est décentralisée, il est nécessaire de communiquer avec d'autres nœuds via un réseau p2p pour maintenir la cohérence des données d'état.

La couche d’exécution n’est pas responsable de la détermination de l’ordre des transactions, mais uniquement de l’exécution des transactions et de l’enregistrement des changements d’état après leur exécution. Il existe deux formes d’enregistrement ici, l’une consiste à enregistrer tous les changements d’état sous forme de blocs, et l’autre consiste à enregistrer l’état actuel dans la base de données. Dans le même temps, la couche d’exécution est également le point d’entrée des transactions, et les transactions qui n’ont pas encore été regroupées dans des blocs sont stockées via le pool de transactions. Si d’autres nœuds ont besoin d’accéder aux données de bloc, d’état et de transaction, la couche d’exécution envoie ces informations via le réseau P2P.

Pour la couche d'exécution, il y a trois modules clés : le calcul, le stockage et le réseau. Le calcul correspond à l'implémentation de l'EVM, le stockage correspond à l'implémentation de l'ethdb, et le réseau correspond à l'implémentation du devp2p. Avec une telle compréhension globale, il est possible d'approfondir la compréhension de chaque sous-module sans se perdre dans les détails spécifiques.

07\Ref

[1]

[2]

[3]

[4]

[5]

[6]

·FIN·

Contenu | Ray

Édition & Mise en page | Huán huán

Design | Daisy

Voir l'original
Le contenu est fourni à titre de référence uniquement, il ne s'agit pas d'une sollicitation ou d'une offre. Aucun conseil en investissement, fiscalité ou juridique n'est fourni. Consultez l'Avertissement pour plus de détails sur les risques.
  • Récompense
  • Commentaire
  • Partager
Commentaire
0/400
Aucun commentaire
  • Épingler
Trader les cryptos partout et à tout moment
qrCode
Scan pour télécharger Gate.io app
Communauté
Français (Afrique)
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)