- IDMarket Desserte à roulettes bois façon hêtre et portes noires 76 cmVous venez de tomber sur le rangement idéal pour votre intérieur ! Grâce à votre nouvelle desserte, vous allez pouvoir aménager votre cuisine comme bon vous semble ! Outre toutes ses fonctions vous venez de trouver un produit design et pratique. Profitez de ses deux rangements sur le côté pour y stocker vos huiles, vinaigres et épices. Gardez ainsi tous vos condiments à portée de main pendant que vous cuisinez !Mobile grâce à ses 4 roulettes, vous pourrez la déplacer à votre guise pour trouver la configuration parfaite ! Son design soigné et contemporain s'adapte à tout type de cuisine. Ouvrez les portes noires design du meuble et découvrez son large rangement ! Quoi de mieux pour pouvoir empiler des montagnes de vaisselles, de torchons, de conserves ou de produits d'entretien.Ses multifonctions ne s'arrêtent pas là ! Relevez votre tête : une grande niche de rangement se trouve juste au-dessus du placard. Il vous offre l'espace parfait pour entreposer des denrées périssables.Le meuble est recouvert d'un large plateau ainsi que d'une tablette coulissante. Utilisez cette surface pour cuisiner ou continuer votre rangement.En plus de toutes ces solutions de rangement et ces avantages, vous choisissez une desserte élégante et moderne, idéale avec votre déco intérieure.Alors n'hésitez plus et alliez praticité et esthétisme en un clin d'œil grâce à cette belle desserte de cuisine COSI ! Dimensions de la desserte façon hêtre portes noires- Dimensions totales : Longueur 76 cm x Profondeur 39,5 cm x Hauteur 85 cm- Dimensions du placard fermé : L. 53 x P. 39,5 x H.51 cm- Dimensions des étagères de gauche : L.23 x H. 40 cm- Dimensions des portes noires : L. 24,5 x H. 48 cm- Dimensions du plateau coulissant sur rail : L. 53 x P. 35 x H. 70 cm- 4 roulettes dont 2 avec frein, Hauteur au-dessus du sol : 5 cm- Panneaux de particules 15 mm, 12 mm au niveau des portes- Fond de placard en MDF de 2 mm- Coloris : bois façon hêtre et portes noires- À monter soi-mêmeCe modèle COSI est disponible en différents coloris sur notre boutique en ligne :- Desserte de cuisine COSI bois noir et plateaux façon hêtre- Desserte de cuisine COSI bois blanc et plateaux façon hêtreRetrouvez l'ensemble de nos meubles et éléments de cuisine sur notre boutique en ligne !
- Cube VTT - REACTION TM Pro - 2025 - 27.5" - rawmetal / reflectCUBE VTT - REACTION TM Pro - 2025 - 27.5" - rawmetal / reflect Il y a plus d'une façon de descendre un sentier difficile. Construit pour le plaisir et le contrôle en toute sécurité sur les sentiers les plus difficiles, le CUBE Reaction TM Pro vous soutient - et la géométrie progressive du cadre n'est qu'un début. Les cyclistes expérimentés reconnaîtront le fait que la fourche de 140 mm porte le nom légendaire de Marzocchi Bomber Z2, et il y a une raison à cela - aucun autre modèle de fourche n'a fait plus pour élever la barre de la conduite difficile au fil des ans. Les roues Newmen Performance 30 sont chaussées de pneus Maxxis Assegai 2,5" et Maxxis Dissector 2,4", pour que vous puissiez garder le côté caoutchouc au sol. Les freins à disque hydrauliques Shimano sont dotés d'un rotor de 203 mm à l'avant, pour une meilleure puissance de freinage, même dans des conditions difficiles. Les vitesses 1x12 Deore de Shimano assurent des changements de vitesse impeccables, à chaque fois. Ajoutez la tige de descente déportée, et vous obtenez un ensemble complet. Caractéristiques du CUBE REACTION TM Pro : Cadre Aluminium Lite Formage mécanique avancé Soudure lisse Points de fixation de la béquille, du garde-boue et du porte-bagages Passage de câbles intégré
- Catena Zapata Adrianna Vineyard Mundus Bacillus Terrae Malbec 2020En 1970, après un voyage en Californie, Nicolás Catena découvre une nouvelle façon de faire les choses. Avec toutes ses découvertes, il est retourné à Mendoza, dans la cave familiale fondée par son grand-père Domingo au début du XXème siècle, prêt à mettre en pratique tout ce qu'il avait appris. Pionnier dans son entreprise, Nicolás a été encouragé à trouver la qualité des raisins en haute altitude. Au début, personne ne pensait que cela fonctionnerait, mais leurs efforts ont porté leurs fruits. Grâce à un travail ardu, il a trouvé des vignobles très intéressants. L'un d'entre eux, le plus spectaculaire, a été baptisé du nom de sa fille Adrianna. Ici, à Tupungato, à près de 1 500 mètres d'altitude et au pied des Andes, on cultive un Malbec, un Cabernet Sauvignon et un sublime Chardonnay pour produire les meilleurs vins de Catena Zapata. Parmi eux, le Catena Zapata Adrianna Vineyard Mundus Bacillus Terrae Malbec. Toutefois, l'excellence de ces vins n'est pas le fruit du hasard. Le Catena Institute of Wine, l'équipe de la cave, qui comprend Laura Catena (la fille de Nicolás), se consacre à l'étude de chacune de ces parcelles. Peu de terrains dans le reste du monde ont été étudiés autant que celui-ci, ce qui a permis de mettre en exergue ses avantages et ses secrets. La plupart d'entre eux sont sans doute liés à l'altitude, un facteur qui influence inévitablement les heures de clarté et les températures. Il a ainsi été constaté que plus l'altitude est élevée, plus l'intensité et les heures d'ensoleillement sont importantes. Cela favorise évidemment la photosynthèse et amène la plante à développer des raisins à la peau plus épaisse, à l’instar d’un écran protecteur, pour protéger les graines du soleil. Dans un deuxième temps, on a découvert que plus l'altitude est élevée, plus la température est basse, et les vignes poussent dans un environnement beaucoup plus frais. Ces deux facteurs seront fondamentaux pendant le processus de maturation du raisin. D'autre part, le sol sera également déterminant pour forger le caractère du Catena Zapata Adrianna Vineyard Mundus Bacillus Terrae Malbec. En particulier, cette parcelle de 1,4 hectare est très particulière, car elle possède un sous-sol volcanique recouvert de calcaire, de carbonates de calcium et de fossiles marins déposés au fil des siècles. Cela signifie que malgré les matériaux présents à sa surface, le sol présente un excellent drainage, favorisant l'évacuation de l'eau par les crêtes et empêchant la prolifération des maladies fongiques. Ces sols sont également riches en bactéries qui survivent dans les racines, aidant ainsi la plante à survivre (d'où le nom « mundus bacillus terrae » signifiant « microbes élégants de la terre »). Naturellement, tous ces micro-organismes, qui prolifèrent grâce à l'humidité des brumes matinales, participent à la fermentation du Catena Zapata Adrianna Vineyard Mundus Bacillus Terrae Malbec. Ce processus se déroule en partie dans des cuves ovoïdes en ciment (où il est...
Maintenant que vous avez une vue d’ensemble de 10000 pieds de ce qu’est une chaîne de blocs, approfondissons les principaux composants du système Ethereum:
- comptes
- Etat
- essence et frais
- transactions
- bloquer
- exécution de transaction
- accent
- preuve de travail
Une remarque avant de commencer: quand je dis « hachage » de X, je me réfère à KECCAK-256 hash, qu’Ethereum utilise.
L ‘ »état partagé » global d’Ethereum se compose de nombreux petits objets (« comptes ») qui peuvent interagir les uns avec les autres via un cadre axé sur les messages. Chaque compte en a un Etat associé et 20 octets adresse. Une adresse dans Ethereum est un identifiant 160 bits utilisé pour identifier un compte.
Il existe deux types de comptes:
- Comptes externes, c’est-à-dire est contrôlé par des clés privées et à avoir aucun code ne leur est associé.
- Comptes de contrat, c’est-à-dire est contrôlé par leur code de contrat et ont un code qui leur est associé.
Comptes détenus en externe par rapport aux comptes contractuels
Il est important de comprendre une différence fondamentale entre les comptes externes et les comptes contractuels. Un compte externe peut envoyer des messages à d’autres comptes externes OU à d’autres comptes contractuels en créant et en signant une transaction avec leur clé privée. Un message entre deux comptes externes est simplement un transfert de valeur. Mais un message d’un compte externe à un compte de contrat active le code de compte du contrat et lui permet d’effectuer diverses actions (par exemple, transférer des jetons, écrire dans le stockage interne, créer de nouveaux jetons, effectuer n’importe quel calcul, créer de nouveaux contrats, etc.).
Contrairement aux comptes externes, les comptes contractuels ne peuvent pas initier seuls de nouvelles transactions. Au lieu de cela, les comptes de contrat ne peuvent déclencher des transactions qu’en réponse à d’autres transactions qu’ils ont reçues (à partir d’un compte externe ou d’un autre compte de contrat). Nous vous en apprendrons plus sur les appels à contrats en « Transactions et messages« section.
Par conséquent, toutes les actions qui ont lieu sur la blockchain Ethereum sont toujours mises en mouvement par des transactions tirées de comptes contrôlés de l’extérieur.
Statut du compte
Le compte Etat se compose de quatre composants, indépendants du type de compte:
- nonce: Si le compte est un compte externe, ce nombre représente le nombre de transactions envoyées à partir de l’adresse du compte. Si le compte est un compte de contrat, la déduction est le nombre de contrats créés par le compte.
- équilibre: Le nombre de Wei appartenant à cette adresse. Il y a 1er + 18 Wei par éther.
- racine de stockage: Un hachage du nœud racine sur un arbre Merkle Patricia (nous expliquerons l’arbre Merkle plus tard). Cette arborescence code le hachage pour le contenu de stockage de ce compte et est par défaut vide.
- codeHash: Hash depuis EVM (Ethereum Virtual Machine – plus d’informations à ce sujet plus tard) pour ce compte. Pour les comptes de contrat, il s’agit du code haché et stocké en tant que codeHash. Pour les comptes externes, codeHash le champ est le hachage de la chaîne vide.
Gouvernement mondial
D’accord, nous savons donc que l’état global d’Ethereum consiste en un mappage entre les adresses de compte et les statuts de compte. Ce mappage est stocké dans une structure de données connue sous le nom de Arbre Merkle Patricia.
Un arbre Merkle (ou aussi appelé « tri Merkle ») est un type d’arbre binaire qui se compose d’un ensemble de nœuds avec:
- un grand nombre de nœuds foliaires au bas de l’arbre contenant des données sous-jacentes
- un ensemble de nœuds intermédiaires, où chaque nœud est un hachage pour ses deux nœuds enfants
- un nœud racine unique, également formé par un hachage pour ses deux nœuds enfants, qui représente le sommet de l’arbre
Les données au bas de l’arbre sont générées en divisant les données que nous voulons stocker piècespuis divisez les morceaux en seaux, puis prenez le hachage pour chaque compartiment et répétez le même processus jusqu’à ce que le nombre total de hachages devienne un: hachage racine.
Cet arbre doit avoir une clé pour chaque valeur qui y est stockée. Depuis le nœud racine de l’arborescence, la clé doit indiquer le nœud enfant à suivre pour arriver à la valeur correspondante stockée dans les nœuds feuilles. Dans le cas d’Ethereum, le mappage est la clé / valeur de l’arborescence d’état entre les adresses et leurs comptes associés, y compris le solde, le nonce, le codeHash et le storageRoot pour chaque compte (où storageRoot lui-même est un arbre).
La même arborescence est également utilisée pour stocker les transactions et les reçus. Plus spécifiquement, chaque bloc possède un « en-tête » qui stocke le hachage pour le nœud racine pour trois structures de trie Merkle différentes, notamment:
- State trie
- Transactions trie
- Reçu trie
La capacité de stocker efficacement toutes ces informations dans les tentatives de Merkle est extrêmement utile dans Ethereum pour ce que nous appelons des « clients légers » ou des « nœuds légers ». N’oubliez pas qu’une blockchain est maintenue par de nombreux nœuds. Généralement, il existe deux types de nœuds: les nœuds complets et les nœuds légers.
Un nœud d’archivage complet synchronise la chaîne de blocs en téléchargeant la chaîne entière, du bloc de genèse au bloc principal actuel, en exécutant toutes les transactions qu’elle contient. Normalement, les mineurs stockent l’intégralité du nœud d’archive car ils doivent le faire pour le processus d’exploration de données. Il est également possible de télécharger un nœud complet sans effectuer de transaction. Quoi qu’il en soit, tous les nœuds complets contiennent la chaîne entière.
Mais à moins qu’un nœud ne doive exécuter chaque transaction ou simplement interroger des données historiques, il n’est vraiment pas nécessaire de stocker la chaîne entière. C’est là qu’intervient le concept de nœud lumineux. Au lieu de télécharger et de stocker la chaîne entière et d’exécuter toutes les transactions, les nœuds légers ne chargent la chaîne qu’avec des en-têtes, du bloc de genèse à la tête actuelle, sans effectuer de transactions ni obtenir aucun état associé. Étant donné que les nœuds légers ont accès aux têtes de bloc, qui contiennent des hachages sur trois tentatives, ils peuvent toujours facilement générer et obtenir des réponses vérifiables sur les transactions, les événements, les soldes, etc.
La raison pour laquelle cela fonctionne est que les hachages dans l’arborescence Merkle se propagent vers le haut – si un utilisateur malveillant essaie d’échanger une fausse transaction au bas d’une arborescence Merkle, cette modification entraînera une modification du hachage dans le nœud ci-dessus, ce qui changera le hachage du nœud ci-dessus, et ainsi de suite, jusqu’à ce qu’il change finalement la racine de l’arbre.
Tout nœud qui souhaite vérifier un ensemble de données peut utiliser quelque chose appelé « preuve Merkle » pour le faire. Un certificat Merkle comprend:
- Un peu de données à vérifier et son hachage
- Hachage de racine d’arbre
- La « branche » (tous les hachages partenaires remontent le chemin du bit à la racine)
Ceux qui lisent les preuves peuvent vérifier que le hachage de cette branche est cohérent tout au long de l’arbre et que le bit donné est en fait à cette position dans l’arbre.
En résumé, l’avantage d’utiliser un arbre Merkle Patricia est que le nœud racine de cette structure dépend cryptographiquement des données stockées dans l’arbre, et donc le hachage du nœud racine peut être utilisé comme une identité sécurisée pour ces données. Étant donné que l’en-tête de bloc contient l’état du hachage racine, des transactions et des arbres de réception, chaque nœud peut valider une petite partie de l’état d’Ethereum sans avoir à stocker l’état entier, qui peut être illimité en taille.
Un concept très important dans Ethereum est le concept de frais. Chaque calcul effectué à la suite d’une transaction sur le réseau Ethereum entraîne des frais – il n’y a pas de déjeuner gratuit! Ces frais sont payés dans une dénomination appelée «gaz».
Gaz est l’unité utilisée pour mesurer les frais requis pour un calcul particulier. Prix du gaz est la quantité d’éther que vous êtes prêt à dépenser pour chaque unité de gaz et est mesurée en «gwei». « Wei » est la plus petite unité d’éther, où 1⁰¹⁸ Wei représente 1 éther. Un gwei est 1 000 000 000 Wei.
Pour chaque transaction, un expéditeur en définit un gasgräns et prix du gaz. Le produit de prix du gaz et gasgräns représente le montant maximum de Wei que l’expéditeur est prêt à payer pour effectuer une transaction.
Par exemple, supposons que l’expéditeur fixe la limite de gaz à 50 000 et un prix du gaz à 20 gwei. Cela signifie que l’expéditeur est prêt à dépenser un maximum de 50 000 x 20 gwei = 1 000 000 000 000 Wei = 0,001 Ether pour terminer la transaction.
N’oubliez pas que la limite de gaz représente le gaz maximal auquel l’expéditeur est prêt à dépenser de l’argent. S’ils ont suffisamment d’Ether dans le solde de leur compte pour couvrir ce maximum, ils sont prêts à partir. L’expéditeur est remboursé pour le gaz non utilisé à la fin de la transaction, échangé contre le taux d’origine.
Dans le cas où l’expéditeur ne fournirait pas le gaz nécessaire pour effectuer la transaction, la transaction est « fin de gaz » et est considérée comme invalide. Dans ce cas, le traitement de la transaction est terminé et tout changement d’état s’est produit, nous nous retrouvons donc dans l’état d’Ethereum avant la transaction. De plus, un enregistrement de la transaction qui échoue est enregistré, indiquant quelle transaction a été tentée et où elle a échoué. Et puisque la machine faisait déjà des efforts pour exécuter les calculs avant de se retrouver au gaz, logiquement, aucun des gaz n’est remboursé à l’expéditeur.
Où va exactement cet argent du gaz? Tout l’argent que l’expéditeur dépense en essence est envoyé à l’adresse du « destinataire », qui est généralement l’adresse du mineur. Parce que les mineurs dépensent les dépenses pour effectuer des calculs et valider les transactions, les mineurs reçoivent les frais d’essence en récompense.
En règle générale, plus le prix du gaz que l’expéditeur est prêt à payer est élevé, plus la valeur que le mineur reçoit de la transaction est élevée. Ainsi, les mineurs les plus susceptibles le choisiront. De cette façon, les mineurs sont libres de choisir les transactions qu’ils souhaitent valider ou ignorer. Pour guider les expéditeurs sur le prix du gaz à fixer, les mineurs ont la possibilité de commercialiser le prix minimum pour lequel ils effectueront des transactions.
Il y a aussi des frais de stockage
Non seulement le gaz est utilisé pour payer les étapes de calcul, mais il est également utilisé pour payer l’utilisation du stockage. La charge totale de stockage est proportionnelle au plus petit multiple de 32 octets utilisé.
Les frais de stockage ont des aspects nuancés. Par exemple, parce qu’un stockage accru augmente la taille de la base de données d’état Ethereum sur Tout nœuds, il y a une incitation à maintenir la petite quantité de données stockées. Pour cette raison, si une transaction comporte une étape qui efface une entrée dans l’espace de stockage, les frais pour effectuer cette opération sont annulés et remboursés pour libérer de l’espace de stockage.
Quel est le but des frais?
Un aspect important du fonctionnement d’Ethereum est que chaque opération unique effectuée par le réseau est effectuée simultanément par chaque nœud complet. Cependant, les étapes de calcul sur Ethereum Virtual Machine sont très coûteuses. Par conséquent, les contrats intelligents Ethereum sont mieux utilisés pour des tâches simples, telles que l’exécution d’une logique métier simple ou la vérification de signatures et d’autres objets cryptographiques, plutôt que pour des utilisations plus complexes, telles que le stockage de fichiers, le courrier électronique ou l’apprentissage automatique, qui peuvent mettre à rude épreuve le réseau. La charge empêche les utilisateurs de surcharger le réseau.
Ethereum est un langage complet de Turing. (En bref, une machine Turing est une machine qui peut simuler n’importe quel algorithme informatique (pour ceux qui ne connaissent pas les machines Turing, vérifiez ceci et cela). Cela permet des boucles et rend Ethereum sensible au problème d’arrêt, un problème où vous ne peut pas déterminer si un programme fonctionnera à l’infini. S’il n’y avait pas de frais, un acteur malveillant peut facilement essayer de perturber le réseau en exécutant une boucle sans fin dans une transaction, sans aucune conséquence, par conséquent, charge le réseau d’attaques délibérées.
Vous vous demandez peut-être « pourquoi devons-nous également payer pour le stockage? » Eh bien, tout comme le calcul, le stockage dans le réseau Ethereum est un coût que l’ensemble du réseau doit alléger.
Nous avons noté plus tôt que Ethereum est l’un machine d’état basée sur les transactions. En d’autres termes, les transactions qui ont lieu entre différents comptes sont ce qui déplace l’état global d’Ethereum d’un état à un autre.
Dans le sens le plus élémentaire, une transaction est un élément d’instructions signé par cryptographie généré par un compte externe, sérialisé puis envoyé à la blockchain.
Il existe deux types de transactions: conversations par message et créations de contrat (c’est-à-dire les transactions qui créent de nouveaux contrats Ethereum).
Toutes les transactions contiennent les composants suivants, quel que soit leur type:
- nonce: un nombre du nombre de transactions envoyées par l’expéditeur.
- gasPrice: le nombre de Wei que l’expéditeur est prêt à payer par unité de gaz nécessaire pour achever la transaction.
- gasLimit: la quantité maximale de gaz que l’expéditeur est prêt à payer pour effectuer cette transaction. Ce montant est fixé et payé à l’avance avant tout calcul.
- à: Adresse du destinataire. Dans une transaction créant une transaction, l’adresse du contrat n’existe pas encore et par conséquent une valeur vide est utilisée.
- valeur: la quantité de Wei à transmettre de l’expéditeur au récepteur. Dans un contrat créant un contrat, cette valeur sert de solde de départ dans le compte de contrat nouvellement créé.
- v, r, s: utilisé pour générer la signature qui identifie l’expéditeur de la transaction.
- dedans (disponible uniquement pour les transactions de création de transaction): un extrait de code EVM utilisé pour initialiser le nouveau compte de contrat. dedans est exécuté une seule fois puis jeté. Quand dedans lors de sa première exécution, il renvoie le corps principal du code de compte, qui est le code de code qui est associé en permanence au compte de contrat.
- Les données (champ facultatif réservé à l’appel de message): saisissez les données (c’est-à-dire les paramètres) pour l’appel de message. Par exemple, si un contrat intelligent sert de service d’enregistrement de domaine, un appel à cet accord peut attendre des champs de saisie tels que le domaine et l’adresse IP.
Nous avons appris en « comptes»Section selon laquelle les transactions – à la fois les appels de messages et les transactions créant des contrats – sont toujours initiées par des comptes externes et envoyées à la blockchain. Une autre façon de voir les choses est que les transactions sont ce qui relie le monde extérieur à l’état intérieur d’Ethereum.
Mais cela ne signifie pas que les contrats ne peuvent pas parler à d’autres contrats. Les contrats qui sont à la portée mondiale de Ethereum State peuvent communiquer avec d’autres contrats dans la même mesure. Comment ils le font via des « messages » ou des « transactions internes » vers d’autres contrats. Nous pouvons penser à des messages ou des transactions internes similaires aux transactions, à la différence près qu’ils ne sont PAS générés par des comptes externes. Au lieu de cela, ils sont générés par le biais de contrats. Ce sont des objets virtuels qui, contrairement aux transactions, ne sont pas sérialisés et n’existent que dans l’environnement d’exécution Ethereum.
Lorsqu’un contrat envoie une transaction interne à un autre contrat, le code associé qui se trouve dans le compte du destinataire est exécuté.
Il est important de noter que les transactions ou messages internes n’en contiennent pas gasLimit. En effet, la limite de gaz est déterminée par le créateur externe de la transaction d’origine (c’est-à-dire un compte appartenant à des tiers). La limite de gaz fixée par le compte externe doit être suffisamment élevée pour pouvoir exécuter la transaction, y compris toute sous-exécution résultant de cette transaction, comme les avis de contrat. Si, dans une chaîne de transactions et de messages, une certaine exécution de message s’épuise, l’exécution de ce message reviendra, ainsi que tous les messages ultérieurs déclenchés par l’exécution. Cependant, l’orientation parentale n’a pas à revenir.
Toutes les transactions sont regroupées en « blocs ». Une blockchain contient une série de ces blocs qui sont enchaînés.
Dans Ethereum, un bloc se compose de:
- le en-tête de bloc
- des informations sur ensemble de transactions est inclus dans ce bloc
- une ensemble d’autres têtes de bloc pour le bloc actuel.
Omerers a expliqué
Qu’est-ce que c’est qu’un « ommer »? Un ommer est un bloc dont le parent est égal au parent du bloc actuel. Jetons un coup d’œil à ce qui est utilisé et pourquoi un bloc contient des têtes de bloc pour cela.
En raison de la façon dont Ethereum est construit, les temps de blocage sont beaucoup plus courts (~ 15 secondes) que d’autres chaînes de blocs, comme Bitcoin (~ 10 minutes). Cela permet un traitement plus rapide des transactions. Cependant, l’un des inconvénients des temps de bloc plus courts est que les mineurs trouvent des solutions de bloc plus compétitives. Ces blocs concurrents sont également appelés « blocs orphelins » (c’est-à-dire que les blocs cassés ne parviennent pas à la chaîne principale).
Le but de ceci est d’aider à récompenser les mineurs pour inclure ces orphelins. Les horloges que les mineurs incluent doivent être « valides », c’est-à-dire au sein de la sixième génération ou moins du bloc actuel. Après six enfants ne peuvent plus être référés à des blocs orphelins périmés (car les transactions plus anciennes compliqueraient un peu les choses).
Chaque bloc reçoit une récompense plus petite qu’un bloc complet. Pourtant, les mineurs sont toujours incités à inclure ces blocs orphelins et à récolter une récompense.
En-tête de bloc
Revenons aux blocs un instant. Nous avons mentionné plus tôt que chaque bloc a une tête de bloc, mais qu’est-ce que c’est?
Un en-tête de bloc est une partie du bloc qui comprend:
- parentHash: un hachage dans l’en-tête du bloc parent (c’est ce qui fait du bloc une « chaîne »)
- ommersHash: un hachage pour la liste d’ommers du bloc en cours
- Bénéficiaire: l’adresse du compte qui reçoit les frais de rupture de ce bloc
- Racine d’état: hachage à partir du nœud racine du nœud d’état (rappelez-vous comment nous avons appris que la trace d’état est stockée dans l’en-tête et permet aux clients faciles de vérifier quelque chose sur l’état)
- racine de transaction: hachage à partir du nœud racine du trie contenant toutes les transactions répertoriées dans ce bloc
- reçusRoot: hachage du nœud racine trien contenant les reçus pour toutes les transactions répertoriées dans ce bloc
- logsBloom: un filtre Bloom (structure de données) composé d’informations de journal
- difficulté: le niveau de difficulté de ce bloc
- figure: nombre de blocs en cours (le bloc de genèse a un numéro de bloc de zéro; le nombre de blocs augmente de 1 pour chaque bloc suivant)
- gasLimit: la limite de gaz actuelle par bloc
- gasUsed: la somme du gaz total utilisé par les transactions dans ce bloc
- horodatage: l’horodatage unix pour le début de ce bloc
- donnée supplémentaire: données supplémentaires liées à ce bloc
- mixHash: un hachage qui, combiné avec nonce, prouve que ce bloc a effectué suffisamment de calculs
- nonce: un hachage qui, lorsqu’il est combiné avec mixHash, prouve que ce bloc a effectué suffisamment de calculs
Remarquez comment chaque en-tête de bloc contient trois tri-structures pour:
- Etat (Racine d’état)
- transactions (racine de transaction)
- le reçu (reçusRoot)
Ces trois structures ne sont que les expériences de Merkle Patricia dont nous avons discuté précédemment.
De plus, certains termes de la description ci-dessus méritent d’être clarifiés. Regardons.
Journal
Ethereum permet aux journaux de permettre le suivi de diverses transactions et messages. Un contrat peut générer explicitement un journal en définissant des «événements» auxquels il souhaite se connecter.
Une entrée de journal contient:
- l’adresse du compte de l’enregistreur,
- une série de sujets représentant différents événements réalisés dans le cadre de cette transaction; et
- toutes les informations relatives à ces événements.
Les journaux sont stockés dans un filtre à fleurs, qui stocke efficacement les données de journal infinies.
Reçu de transaction
Les journaux stockés dans l’en-tête proviennent des informations de journal dans le reçu de transaction. Tout comme vous recevez un reçu lorsque vous achetez quelque chose dans un magasin, Ethereum génère un reçu pour chaque transaction. Comme vous vous en doutez, chaque reçu contient des informations sur la transaction. Ce reçu contient des éléments tels que:
- numéro de bloc
- hachage de bloc
- hachage de transaction
- gaz utilisé par la transaction en cours
- gaz cumulé utilisé dans le bloc en cours après la conclusion de la transaction en cours
- journaux créés lors de l’exécution de la transaction en cours
- ..etc
Difficultés de blocage
La «difficulté» d’un bloc est utilisée pour assurer la cohérence pendant le temps de validation des blocs. Le bloc de genèse a une difficulté de 131 072, et une formule spéciale est utilisée pour calculer la difficulté de chaque bloc par la suite. Si un bloc donné est validé plus rapidement que le bloc précédent, le protocole Ethereum augmente la difficulté de ce bloc.
La difficulté du bloc affecte nonce, qui est un hachage qui doit être calculé lors de l’extraction d’un bloc à l’aide de l’algorithme de preuve de travail.
Relation entre le bloc difficulté et nonce est mathématiquement formalisé comme:
où haute définition c’est la difficulté.
La seule façon de trouver un défaut qui rencontre une limite de difficulté est d’utiliser l’algorithme de preuve de travail pour énumérer toutes les possibilités. Le temps attendu pour trouver une solution est proportionnel à la difficulté – plus la difficulté est élevée, plus il est difficile de trouver le nonce, et plus il est difficile de valider le bloc, ce qui à son tour augmente le temps nécessaire pour valider un nouveau bloc. Ainsi, en ajustant la difficulté avec un bloc, le protocole peut ajuster le temps qu’il faut pour valider un bloc.
Si le temps de validation devient plus lent, le protocole réduit la difficulté. De cette façon, le temps de validation est ajusté pour maintenir une vitesse constante – en moyenne un bloc toutes les 15 secondes.
Nous sommes arrivés à l’une des parties les plus complexes du protocole Ethereum: l’exécution d’une transaction. Supposons que vous envoyez une transaction au réseau Ethereum pour qu’elle soit traitée. Qu’advient-il du passage à Ethereum pour inclure votre transaction?
Tout d’abord, toutes les transactions doivent répondre à un ensemble initial d’exigences pour être réalisées. Ceux-ci inclus:
- La transaction doit être formatée correctement RLP. « RLP » signifie « Recursive Length Prefix » et est un format de données utilisé pour coder des tableaux imbriqués de données binaires. RLP est le format qu’Ethereum utilise pour sérialiser des objets.
- Signature de transaction valide.
- Taux de transaction valide. N’oubliez pas qu’un compte n’est pas le nombre de transactions envoyées à partir de ce compte. Pour être valide, un taux de transaction doit être égal à l’écart du compte de l’expéditeur.
- La limite de gaz de la transaction doit être égale ou supérieure à gaz inhérent utilisé par la transaction. Le gaz inhérent comprend:
- un coût prédéfini de 21 000 gaz pour finaliser la transaction
- une redevance gaz pour les données envoyées avec la transaction (4 gaz pour chaque octet de données ou code égal à zéro, et 68 gaz pour chaque octet non nul de données ou code)
- si la transaction est une transaction créant un contrat, 32 000 gaz supplémentaires
- Le solde du compte de l’expéditeur doit contenir suffisamment d’Ether pour couvrir Coûts du gaz «avancés» que l’expéditeur doit payer. Le calcul du coût du gaz à l’avance est simple: tout d’abord, la transaction gasgräns multiplié par la transaction prix du gaz pour déterminer le coût maximum du gaz. Par la suite, ce coût maximum est ajouté à la valeur totale transmise de l’expéditeur au récepteur.
Si la transaction répond à toutes les exigences de validité ci-dessus, nous passons à l’étape suivante.
Tout d’abord, nous déduisons le coût d’exécution du bilan de l’expéditeur et augmentons le compte de l’expéditeur de 1 sur le compte de la transaction en cours. À ce stade, nous pouvons calculer le gaz résiduel comme limite totale de gaz pour la transaction moins le gaz utilisé.
Ensuite, la transaction commence à s’exécuter. Tout au long de l’exécution d’une transaction, Ethereum garde une trace du «substitut». Ce sous-état est un moyen d’enregistrer les informations collectées pendant la transaction qui seront nécessaires immédiatement après la transaction. Plus précisément, il contient:
- Ensemble autodestructeur: un ensemble de comptes (le cas échéant) qui seront rejetés une fois la transaction terminée.
- série de journaux: points de contrôle archivés et indexables pour l’exécution de code de la machine virtuelle.
- Solde de remboursement: le montant à rembourser sur le compte de l’expéditeur après la transaction. Rappelez-vous comment nous avons mentionné que le stockage dans Ethereum coûte de l’argent et qu’un expéditeur est remboursé pour la compensation du stockage? Ethereum en assure le suivi avec un compteur de remboursement. Le compteur de remboursement commence à zéro et augmente chaque fois que le contrat supprime quelque chose en stock.
Ensuite, les différents calculs requis par la transaction sont traités.
Une fois que toutes les étapes requises par la transaction ont été traitées et à condition qu’il n’y ait pas de permis non valide, l’état est finalisé en déterminant la quantité de gaz inutilisé à rembourser à l’expéditeur. En plus du gaz non utilisé, l’expéditeur se voit également rembourser une certaine compensation du « solde de remboursement » comme nous l’avons décrit ci-dessus.
Une fois l’expéditeur remboursé:
- l’éther pour le gaz est donné au mineur
- le gaz utilisé par la transaction est ajouté au compteur de gaz du bloc (qui garde la trace du gaz total utilisé par toutes les transactions dans le bloc et est utile pour valider un bloc)
- tous les comptes de l’ensemble autodestructeur (le cas échéant) sont supprimés
Enfin, nous nous retrouvons avec le nouvel état et un ensemble de journaux créés par la transaction.
Maintenant que nous avons couvert les bases de la réalisation de transactions, examinons quelques-unes des différences entre les transactions créant des transactions et les conversations de message.
Création de contrat
N’oubliez pas qu’il existe deux types de comptes dans Ethereum: les comptes de contrat et les comptes externes. Lorsque nous disons qu’une transaction est une « création de contrat », nous voulons dire que le but de la transaction est de créer un nouveau compte de contrat.
Pour créer un nouveau compte de contrat, nous expliquons d’abord l’adresse du nouveau compte avec une formule spéciale. Ensuite, nous initialisons le nouveau compte par:
- Met nonce à zéro
- Si l’expéditeur a envoyé beaucoup d’Ether comme valeur avec la transaction, définissez le solde du compte à cette valeur
- Soustraire la valeur ajoutée au nouveau solde du compte du solde de l’expéditeur
- Définit le stockage comme vide
- Définissez le hachage du code de contrat comme hachage pour une chaîne vide
Une fois que nous avons initialisé le compte, nous pouvons réellement créer le compte en utilisant initkod est envoyé avec la transaction (voir la section « Transaction et messages » pour une mise à jour du code init). Ce qui se passe pendant l’exécution de ce code d’initialisation varie. Selon le concepteur de contrat, il peut mettre à jour le stockage du compte, créer d’autres comptes de contrat, passer d’autres appels de message, etc.
Lorsque le code pour initialiser un contrat est exécuté, il utilise du gaz. La transaction ne doit pas utiliser plus de gaz que le gaz restant. Si tel est le cas, l’exécution frappera une exception pour les coupures de gaz (OOG) et quittera. Si la transaction est terminée en raison d’une exemption pour l’essence, l’État revient au point immédiatement avant la transaction. L’expéditeur est ne pas remboursé le gaz utilisé avant sa fin.
Buhu.
Cependant, si l’expéditeur a envoyé une valeur Ether avec la transaction, la valeur Ether sera remboursée même si le contrat est créé. Phew!
Si le code d’initialisation est exécuté avec succès, un coût final de création d’un contrat est payé. Il s’agit d’un coût de stockage et est proportionnel à la taille du code de contrat créé (encore une fois, pas de déjeuner gratuit!) S’il n’y a pas assez de gaz pour payer le coût final, la transaction déclare à nouveau une exception pour le gaz et pour annuler.
Si tout se passe bien et que nous arrivons jusque-là sans exception, tout gaz restant non utilisé sera remboursé à l’expéditeur d’origine de la transaction, et l’état modifié peut maintenant continuer!
Hourra!
message Appel
Les performances d’un appel de message sont similaires à celles créées par un contrat, à quelques différences près.
Une exécution d’appel de message n’inclut aucun code d’initialisation car aucun nouveau compte n’est créé. Cependant, il peut contenir des données d’entrée si ces données ont été fournies par l’émetteur de la transaction. Une fois exécutés, les appels de message ont également un composant supplémentaire contenant des données de sortie, qui est utilisé si une exécution ultérieure a besoin de ces données.
Comme c’est le cas avec la création d’un contrat, si un appel de message s’exécute parce qu’il manque de gaz ou parce que la transaction n’est pas valide (par exemple, débordement de pile, destination de saut non valide ou instruction non valide), aucun du gaz utilisé ne sera remboursé à l’appelant d’origine. Au lieu de cela, tout le gaz inutilisé restant est consommé et la condition est rétablie immédiatement avant le transfert du solde.
Jusqu’à la dernière mise à jour d’Ethereum, il n’y avait aucun moyen d’arrêter ou de reprendre l’exécution d’une transaction sans que le système consomme tout le gaz que vous fournissez. Par exemple, supposons que vous ayez signé un contrat qui a généré une erreur lorsqu’un appelant n’était autorisé à exécuter aucune transaction. Dans les versions précédentes d’Ethereum, le gaz restant serait toujours consommé et aucun gaz ne serait remboursé à l’expéditeur. Men Byzantium-uppdateringen innehåller en ny « återvänd » -kod som tillåter ett kontrakt att stoppa exekveringen och återställa tillståndsförändringar, utan att konsumera den återstående gasen, och med möjligheten att returnera en anledning till den misslyckade transaktionen. Om en transaktion genomförs på grund av en återgång, returneras den oanvända gasen till avsändaren.
Hittills har vi lärt oss om den serie steg som måste hända för att en transaktion ska kunna genomföras från början till slut. Nu ska vi titta på hur transaktionen faktiskt genomförs inom VM.
The part of the protocol that actually handles processing the transactions is Ethereum’s own virtual machine, known as the Ethereum Virtual Machine (EVM).
The EVM is a Turing complete virtual machine, as defined earlier. The only limitation the EVM has that a typical Turing complete machine does not is that the EVM is intrinsically bound by gas. Thus, the total amount of computation that can be done is intrinsically limited by the amount of gas provided.
Moreover, the EVM has a stack-based architecture. A stack machine is a computer that uses a last-in, first-out stack to hold temporary values.
The size of each stack item in the EVM is 256-bit, and the stack has a maximum size of 1024.
The EVM has memory, where items are stored as word-addressed byte arrays. Memory is volatile, meaning it is not permanent.
The EVM also has storage. Unlike memory, storage is non-volatile and is maintained as part of the system state. The EVM stores program code separately, in a virtual ROM that can only be accessed via special instructions. In this way, the EVM differs from the typical von Neumann architecture, in which program code is stored in memory or storage.
The EVM also has its own language: “EVM bytecode.” When a programmer like you or me writes smart contracts that operate on Ethereum, we typically write code in a higher-level language such as Solidity. We can then compile that down to EVM bytecode that the EVM can understand.
Okay, now on to execution.
Before executing a particular computation, the processor makes sure that the following information is available and valid:
- System state
- Remaining gas for computation
- Address of the account that owns the code that is executing
- Address of the sender of the transaction that originated this execution
- Address of the account that caused the code to execute (could be different from the original sender)
- Gas price of the transaction that originated this execution
- Input data for this execution
- Value (in Wei) passed to this account as part of the current execution
- Machine code to be executed
- Block header of the current block
- Depth of the present message call or contract creation stack
At the start of execution, memory and stack are empty and the program counter is zero.
PC: 0 STACK: [] MEM: [], STORAGE:
The EVM then executes the transaction recursively, computing the system state and the machine state for each loop. The system state is simply Ethereum’s global state. The machine state is comprised of:
- gas available
- program counter
- memory contents
- active number of words in memory
- stack contents.
Stack items are added or removed from the leftmost portion of the series.
On each cycle, the appropriate gas amount is reduced from the remaining gas, and the program counter increments.
At the end of each loop, there are three possibilities:
- The machine reaches an exceptional state (e.g. insufficient gas, invalid instructions, insufficient stack items, stack items would overflow above 1024, invalid JUMP/JUMPI destination, etc.) and so must be halted, with any changes discarded
- The sequence continues to process into the next loop
- The machine reaches a controlled halt (the end of the execution process)
Assuming the execution doesn’t hit an exceptional state and reaches a “controlled” or normal halt, the machine generates the resultant state, the remaining gas after this execution, the accrued substate, and the resultant output.
Phew. We got through one of the most complex parts of Ethereum. Even if you didn’t fully comprehend this part, that’s okay. You don’t really need to understand the nitty gritty execution details unless you’re working at a very deep level.
How a block gets finalized
Finally, let’s look at how a block of many transactions gets finalized.
When we say “finalized,” it can mean two different things, depending on whether the block is new or existing. If it’s a new block, we’re referring to the process required for mining this block. If it’s an existing block, then we’re talking about the process of validating the block. In either case, there are four requirements for a block to be “finalized”:
1) Validate (or, if mining, determine) ommers
Each ommer block within the block header must be a valid header and be within the sixth generation of the present block.
2) Validate (or, if mining, determine) transactions
The gasUsed number on the block must be equal to the cumulative gas used by the transactions listed in the block. (Recall that when executing a transaction, we keep track of the block gas counter, which keeps track of the total gas used by all transactions in the block).
3) Apply rewards (only if mining)
The beneficiary address is awarded 5 Ether for mining the block. (Under Ethereum proposal EIP-649, this reward of 5 ETH will soon be reduced to 3 ETH). Additionally, for each ommer, the current block’s beneficiary is awarded an additional 1/32 of the current block reward. Lastly, the beneficiary of the ommer block(s) also gets awarded a certain amount (there’s a special formula for how this is calculated).
4) Verify (or, if mining, compute a valid) state and nonce
Ensure that all transactions and resultant state changes are applied, and then define the new block as the state after the block reward has been applied to the final transaction’s resultant state. Verification occurs by checking this final state against the state trie stored in the header.
The “Blocks” section briefly addressed the concept of block difficulty. The algorithm that gives meaning to block difficulty is called Proof of Work (PoW).
Ethereum’s proof-of-work algorithm is called “Ethash” (previously known as Dagger-Hashimoto).
The algorithm is formally defined as:
where m is the mixHash, n is the nonce, Hn is the new block’s header (excluding the nonce and mixHash components, which have to be computed), Hn is the nonce of the block header, and d is the DAG, which is a large data set.
In the “Blocks” section, we talked about the various items that exist in a block header. Two of those components were called the mixHash and the nonce. As you may recall:
- mixHash is a hash that, when combined with the nonce, proves that this block has carried out enough computation
- nonce is a hash that, when combined with the mixHash, proves that this block has carried out enough computation
The PoW function is used to evaluate these two items.
How exactly the mixHash and nonce are calculated using the PoW function is somewhat complex, and something we can delve deeper into in a separate post. But at a high level, it works like this:
A “seed” is calculated for each block. This seed is different for every “epoch,” where each epoch is 30,000 blocks long. For the first epoch, the seed is the hash of a series of 32 bytes of zeros. For every subsequent epoch, it is the hash of the previous seed hash. Using this seed, a node can calculate a pseudo-random “cache.”
This cache is incredibly useful because it enables the concept of “light nodes,” which we discussed previously in this post. The purpose of light nodes is to afford certain nodes the ability to efficiently verify a transaction without the burden of storing the entire blockchain dataset. A light node can verify the validity of a transaction based solely on this cache, because the cache can regenerate the specific block it needs to verify.
Using the cache, a node can generate the DAG “dataset,” where each item in the dataset depends on a small number of pseudo-randomly-selected items from the cache. In order to be a miner, you must generate this full dataset; all full clients and miners store this dataset, and the dataset grows linearly with time.
Miners can then take random slices of the dataset and put them through a mathematical function to hash them together into a “mixHash.” A miner will repeatedly generate a mixHash until the output is below the desired target nonce. When the output meets this requirement, this nonce is considered valid and the block can be added to the chain.
Mining as a security mechanism
Overall, the purpose of the PoW is to prove, in a cryptographically secure way, that a particular amount of computation has been expended to generate some output (i.e. the nonce). This is because there is no better way to find a nonce that is below the required threshold other than to enumerate all the possibilities. The outputs of repeatedly applying the hash function have a uniform distribution, and so we can be assured that, on average, the time needed to find such a nonce depends on the difficulty threshold. The higher the difficulty, the longer it takes to solve for the nonce. In this way, the PoW algorithm gives meaning to the concept of difficulty, which is used to enforce blockchain security.
What do we mean by blockchain security? It’s simple: we want to create a blockchain that EVERYONE trusts. As we discussed previously in this post, if more than one chain existed, users would lose trust, because they would be unable to reasonably determine which chain was the “valid” chain. In order for a group of users to accept the underlying state that is stored on a blockchain, we need a single canonical blockchain that a group of people believes in.
This is exactly what the PoW algorithm does: it ensures that a particular blockchain will remain canonical into the future, making it incredibly difficult for an attacker to create new blocks that overwrite a certain part of history (e.g. by erasing transactions or creating fake transactions) or maintain a fork. To have their block validated first, an attacker would need to consistently solve for the nonce faster than anyone else in the network, such that the network believes their chain is the heaviest chain (based on the principles of the GHOST protocol we mentioned earlier). This would be impossible unless the attacker had more than half of the network mining power, a scenario known as the majority 51% attack.
Mining as a wealth distribution mechanism
Beyond providing a secure blockchain, PoW is also a way to distribute wealth to those who expend their computation for providing this security. Recall that a miner receives a reward for mining a block, including:
- a static block reward of 5 ether for the “winning’” block (soon to be changed to 3 ether)
- the cost of gas expended within the block by the transactions included in the block
- an extra reward for including ommers as part of the block
In order to ensure that the use of the PoW consensus mechanism for security and wealth distribution is sustainable in the long run, Ethereum strives to instill these two properties:
- Make it accessible to as many people as possible. In other words, people shouldn’t need specialized or uncommon hardware to run the algorithm. The purpose of this is to make the wealth distribution model as open as possible so that anyone can provide any amount of compute power in return for Ether.
- Reduce the possibility for any single node (or small set) to make a disproportionate amount of profit. Any node that can make a disproportionate amount of profit means that the node has a large influence on determining the canonical blockchain. This is troublesome because it reduces network security.
In the Bitcoin blockchain network, one problem that arises in relation to the above two properties is that the PoW algorithm is a SHA256 hash function. The weakness with this type of function is that it can be solved much more efficiently using specialized hardware, also known as ASICs.
In order to mitigate this issue, Ethereum has chosen to make its PoW algorithm (Ethhash) sequentially memory-hard. This means that the algorithm is engineered so that calculating the nonce requires a lot of memory AND bandwidth. The large memory requirements make it hard for a computer to use its memory in parallel to discover multiple nonces simultaneously, and the high bandwidth requirements make it difficult for even a super-fast computer to discover multiple nonce simultaneously. This reduces the risk of centralization and creates a more level playing field for the nodes that are doing the verification.
One thing to note is that Ethereum is transitioning from a PoW consensus mechanism to something called “proof-of-stake”. This is a beastly topic of its own that we can hopefully explore in a future post. ☺️
…Phew! You made it to the end. I hope?
There’s a lot to digest in this post, I know. If it takes you multiple reads to fully understand what’s going on, that’s totally fine. I personally read the Ethereum yellow paper, white paper, and various parts of the code base many times before grokking what was going on.
Nonetheless, I hope you found this overview helpful. If you find any errors or mistakes, I’d love for you to write a private note or post it directly in the comments. I look at all of ’em, I promise 😉
And remember, I’m human (yep, it’s true) and I make mistakes. I took the time to write this post for the benefit of the community, for free. So please be constructive in your feedback, without unnecessary bashing. ☺️