HOW DOES ETHEREUM WORK ?

in #ethereum6 years ago (edited)

Introduction

Surely some of you know what the Ethereum blockchain (from the English Ethereum) is, others, on the contrary, do not have even the slightest idea about it. One way or another, the first and second have heard something about this platform. Recently, many articles in various major journals have been devoted to this topic, but for those people who have heard little about Ethereum, all the articles on this topic seem to be something mystical and completely incomprehensible. Then, what is this platform? In short: Ethereum is a publicly accessible database with the ability to store digital transactions for an unlimited time. It is also important to note that the maintenance and protection of such a database does not require any key management systems. Instead, this platform works as a “defenseless” transactional system — a framework in which individuals can perform peer-to-peer transactions, with neither party bearing any obligations to the other or third parties.

I would not be surprised if you understood little. Actually, the purpose of this article is to explain how the ethereum blockchain functions at the technical level, without resorting to this for complex mathematical calculations or formulas that are terrifying in their magnitude. Even if you are not a programmer, I have full confidence that this article will help you understand the principles of Ethereum technology. And even if some parts of this article are crammed with technical definitions that may seem too difficult for you to understand, you should not despair, because its goal is to convey to you an understanding of this platform as a whole, without going into technical and mathematical subtleties.

Many of the topics covered in this article are chewing those basic concepts that you have probably come across more than once, reading yellow paper (from the English paper “yellow paper” is the official specification for Ethereum). I have added my own explanations and diagrams so that you understand the technology as quickly as possible. Well, for the most brave and technically savvy, I can advise reading the Ethereum yellow paper.

Let's get started!

What is blockchain

Blockchain is a cryptographically secure single-element transactional system with a common state. Not the easiest definition, is it? Let's break down each component of this definition into separate parts.

  • "Cryptographically secure" means that the security of a cryptocurrency is provided by sophisticated mathematical algorithms that are almost impossible to circumvent. Protection built using these algorithms is a kind of firewall: thanks to the algorithms used, bypassing the security system is practically impossible (for example, creating fake transactions, deleting transactions, etc.).

  • "Transactional single-element system" means that there is only one specified system state, due to which all transactions created in this system occur. In other words, only one state is provided for this system, which is the only true one.

  • "With shared state" means that the state specified in the system is common and open to all.

Thus, the Ethereum platform implements the above blockchain paradigm.

Paradigm blockchain platform Ethereum

Blockchain Ethereum is, in fact, a system of transaction status . In computer science, such a thing as “state system” or “state machine” is a system that processes the input information and, on the basis of the latter, is transformed into a new state.

In the state machine of Ethereum, all processes begin with the "initial state". Such a state is an analogue of the zero state in which the machine is located until any operations related to transactions begin to occur in its network. When such actions begin to occur, the original state is replaced with the final one, and at any time the final state displays the current state of Ethereum.

Ethereum state has millions of transactions. These transactions are grouped into “blocks.” The block contains a number of transactions, with each subsequent block connected to the previous one, thereby providing a kind of block chain.

The transaction must be correct in order to trigger its transition from one state to another. A transaction is considered correct only when it has passed the verification process - the so-called “mining” . Mining is when a group of nodes (computers) expend their computational resources to create a block of correct transactions.

Any node on the network that declares itself a miner may try to create and test a block of transactions. A common experience is the attempt by many miners to simultaneously create and verify a block of transactions. Each miner provides his mathematical “proof” when sending a block to the blockchain, and this proof acts as a kind of guarantee: if the proof exists, the transactions in the block are considered correct.

The miner must provide his mathematical proof faster than any other competitor does in order for his block to be added to the main blockchain. The process of checking each block, which is the miner’s presentation of his mathematical proof, is called “work proof”.

The miner who justifies the new unit receives a certain reward for doing this work. What kind of reward are we talking about? In the ethereum blockchain, a built-in digital token is used, which is called "ether" (from English ether - "ether"). Every time when a miner justifies his block of transactions, a new token or a new air is created, and the miner receives a reward for creating it.

Then, you may have a completely logical question: where is the guarantee that each miner will stick to only one chain of blocks? How can I make sure that the other team of miners do not decide to create their own block chain?

At the very beginning of this article, we have already cited such a thing as "a single-element transactional system with a common state." Based on this definition, we can conclude that there are no two or more correct current states - it is unique. Thus, everyone who takes part in the process of justifying new blocks should take this statement as true. The presence of several states (or chains) would destroy the entire system, because it would be impossible to agree on which of the states is correct. For example, imagine that there would be several chains of blocks. Then, in theory, you could collect 10 coins on one chain, 20 coins on the other, 40 coins on the third, etc. In this case, it would be impossible to determine which chain is the most "correct".

Whenever multiple paths are generated, a “fork” occurs. Often, ramifications are very undesirable because they violate the integrity of the system, and users have to choose one of the possible chains.

To determine which of the possible paths is correct and to prevent the formation of multiple chains, a method called “GHOST protocol” is used in Ethereum.

GHOST - Greedy Heaviest Observed Subtree - Greedy-and-Most-Grounded-Daughter-Trees

I will try to explain in simple terms: the GHOST protocol declares that we must choose only the path on which the largest number of calculations was performed. To determine this path, you can use the number of the block that was defined last (“leaf block”). Thanks to this approach, you can determine the total number of blocks that are in the current path (without taking into account the initial state block). The higher the block, the longer the path and the more justifications the miners must provide. Based on such considerations, the only correct version is accepted for the current state.

Now that you already have an idea of ​​what a blockchain is, I propose to deal with the main components that make up the Ethereum system:

  • Accounts

  • state

  • fuel reward

  • transactions

  • blocks

  • performing transactions

  • mining

  • justification

A small digression before we begin: at the mention of the X hash, it means the KECCAK-256 hash used in Ethereum.

Accounts

The global general state of the Ethereum platform consists of a set of small objects - accounts that interact with each other through the messaging paradigm. Each account has a specific status and a 20-byte address. The address in Ethereum is a 160-bit identifier used to identify any of the accounts.

In total there are two types of accounts:

  • External accounts are controlled using private keys. However, such entries have no code associated with them.

  • Contract accounts are controlled by a special code specified in the terms of the contract, and having a code associated with them.

External and contract accounts

Let's look at the main differences between external and contract accounts. For an external account, it is possible to send messages to other external accounts, as well as other contract accounts. For this purpose, you must create and register a new transaction using the private key. A message between two external accounts is only a value to send. On the other hand, a message sent from an external account to a contract account implies activation of the contract account code, and it is possible to perform certain actions (for example, you can transfer tokens with this message, write values ​​to the built-in memory, create tokens, perform some calculations, create new contracts, etc.).

With the help of contract accounts, as opposed to external ones, it is impossible to independently initiate new transactions. Instead, using contract accounts, you can only start transactions in response to other received transactions (for example, those received from an external account or from another contract account). For more information about calls between contract accounts, we’ll stop in the “Transactions and Messages” section.

Each action in the Ethereum blockchain takes place due to transactions initiated by externally controlled accounts.

Account Status

The state of each of the accounts, regardless of their type, can take one of four values:

  • nonce : If this account matches an external account, then the resulting number is the number of transactions that were sent from the account address. If the account is a contract account, then the nonce element is the number of contracts created in the account.

  • balance : the total number of wei purchased by this account. For example, each ether that is the Ethereum exchange unit contains 10 ^ 18 wei - fractional parts of the ether.

  • storageRoot : a hash of the root node of the prefix Merkle tree (which is the Merkle tree we will look at a little later). The Merkle tree encodes the hash of the contents of this account, while by default it is empty.

  • codeHash : EVM-code hash (from the English Ethereum Virtual Machine; what it is, I'll tell you a little later) of the account. For contract accounts, this field is a code that is hashed and stored as codeHash.

General system condition

So, we figured out that the global state of Ethereum is a comparison of the account state of the account. This mapping is stored in a data structure - the Merkle prefix tree .

A Merkle tree (or “Merkle trie”) is a type of binary file consisting of a set of nodes, which include:

  • a certain number of leaf nodes, which are located at the bottom of the tree containing basic data;

  • a set of intermediate nodes, each node being a hash of its two child nodes

  • one root node, also formed from a hash of two child nodes, which represents the top of the tree

    The data at the bottom of the tree is created by dividing the data we want to store into separate fragments. Further, such fragments are placed in data storage baskets, after which they are hashed and a similar process is repeated until the total number of hashes is equal to one or the root hash.

    For each value stored inside this tree, you will need to enter a specific key. To get the corresponding value stored in leaf nodes, you must receive a key command: which child node chains should be followed. As for Ethereum, the display of the key / value required for the state tree is between the addresses and associated accounts, including balance, nonce, codeHash, and storageRoot for each of the accounts, with the storageRoot being a tree.

    Such a structure of the prefix tree can also be used to store both transactions and the payment acceptance page. If we dwell on this in more detail, then each block has a so-called “header” or header file that stores the hash of the root node of three different structures of the Merkle tree, including:

  • Prefix Tree State

  • Prefix Tree Transactions

  • Payment acceptance pages for prefix tree

    The ability to efficiently store this information in the prefix tree of the Mercle Ethereum is an incredibly practical solution for so-called thin clients or thin nodes. It should also be noted that the blockchain is supported by a set of nodes. In simple words: there are only two types of nodes: full and thin.

The complete archive node synchronizes the blockchain by loading the entire chain from the initial state block to the current block containing the header file, and all the transactions in it are executed. As a rule, miners keep a complete archive site, because without the latter they will not have the opportunity to participate in the mining process. In addition, you can also download the complete node, and there is no need to complete each individual transaction. It is also worth noting that each complete node always contains a complete chain.

In the event that the node does not need to perform every single transaction or request accumulated data, then storing the complete chain may be redundant. In this case, we are faced with such a concept as a thin knot. In the place of loading and storing the complete chain, as well as performing all transactions, the thin nodes load only the chain of header files from the initial state block into the current header, without performing any transactions. Since thin nodes have access to block headers containing the hash of three prefix trees, they can easily create and retrieve the appropriate responses for transactions, events, balances, etc.

The hash in the Merkle tree extends from the lower branches to the upper ones, and if the attacker attempts to replace the original transaction with a fake one in the lower part of the Merkle tree, this will change the hash of the top node, and this in turn will change the hash of the node above it and so on until, ultimately, it causes a change in the root.

Any node for which verification of any part of the data is required uses the so-called “Merkle proof”. The latter consists of:

  • The piece of data that needs to be verified

  • Tree root hash

  • The so-called "branches" - all hashes, from the checked data fragment to the root.

    Each user who reads such evidence can check whether the hash for a particular branch is appropriate for the entire tree section, and whether the fragment occupies a corresponding position in that tree.

Thus, we can conclude that the advantage of using the Merkle prefix tree is that the root node of this structure is cryptographically dependent on the data stored in the tree. Therefore, the hash of the root node can be used as a secure identifier for this data. Due to the fact that the root hash of trees, as well as their status, transactions, and payment receipt information are included in the block header, any of the nodes can check one or another part of the state of Ethereum without having to store all the states that can be potentially unlimited in size.

Fuel and reward

One of the important points in the Ethereum system is the payment process. For any calculation resulting from transactions with transactions within the Ethereum network, a certain fee is taken. The nominal value of this payment is called "fuel" (from the English. Gas).

Fuel is a unit of measure that is used to determine the amount of payment for a particular calculation. The price of fuel is the amount of "ether" that you are able to spend on each unit of fuel. The price of fuel in gwei is measured. Wei is the smallest unit of ether, where 1018 Wei is just 1 ether. One gwei is equal to 1 000 000 000 Wei.

For any transaction, the sender must set the fuel limit, as well as the price of fuel. The price of fuel and fuel limit is the maximum amount in Wei that the sender is willing to pay to complete the transaction.

Let's imagine that the sender sets the fuel limit to 50,000 gwei and the fuel price to 20 gwei. This means that the sender is ready to spend no more than 50,000 x 20 gwei = 1,000,000,000,000 Wei or 0.001 air to complete this transaction.

Thus, the fuel limit is the maximum amount of fuel that the sender is willing to pay. In the event that there is enough air on the balance of his account to cover this maximum, then the sender can conduct transactions. In addition, the sender is reimbursed for any losses incurred due to the incomplete use of fuel at the conclusion of the transaction, and the fuel will be exchanged at the original rate.

In the event that the sender did not provide the necessary amount of fuel for the transaction, the latter will be carried out "without fuel" and will be considered invalid. Thus, the transaction is interrupted, and any state changes are canceled, as a result of which the Ethereum system returns the transaction participants to their original state. It is worth noting that information about such a failed transaction is recorded in the system, so that you can track which transactions were performed and at what stage the failure occurred. And what is also important: since before the moment the sender ran out of fuel, the car had already spent some effort to make calculations, it would be logical to assume that the losses associated with the expenditure of fuel will not be refunded to the sender.

“Where exactly am I sending fuel ?” You ask. So, all the money that was spent on the purchase by the sender of the fuel is sent to the address of the beneficiary, which in most cases is the address of the miner. Since the miners perform calculations and verification of transactions, they are the ones who receive payment for fuel as a reward.

As a rule, the higher the cost of fuel that the sender wishes to pay, the higher the payment received by the miner as a result of the transaction and, moreover, the more likely that the miner will make his choice in its favor. Thus, miners are free to choose which transaction they want to validate and which transactions they should ignore. Often, miners inform senders what price they should ask for fuel in order to be first prepared to carry out transactions.

Payment for the use of storage

Fuel is used not only to pay for certain calculations, but also to pay for the use of storage. The total fee for using the storage is 32 used bytes.

The issue of payment, charged for the use of storage, has some nuances. For example, since the increase in space used in the storage implies an increase in the size of the Ethereum state database, and this applies to all nodes, you have an incentive to store only a relatively small amount of data. Thus, if any of the stages of a transaction involves deleting an entry in the repository, then payment for this operation will not be charged, and in view of the release of space in the repository, losses will also be reimbursed.

What is the payment for?

An important aspect of Ethereum's work is that any operation that is performed by the network is also simultaneously performed by each complete node. However, all the steps involved in computing an Ethereum virtual machine are very expensive. Thus, for solving simple tasks (for example, launching simple business logic, checking signatures, as well as other operations related to cryptocurrency), Ethereum’s smart contracts can be quite suitable, in contrast to those cases when other, more complex, Tasks: storing files or e-mail, as well as performing tasks from the field of machine learning, which can cause excessive network load. Introduction of payment prevents user actions aimed at excessive network load.

Ethereum uses Turing language. In short: a Turing machine is a machine that mimics any computer algorithm. For those who first hear about the Turing machine, I suggest reading this and this one.articles. Thanks to this feature, it is possible to use cycles in Ethereum, and this makes it susceptible to the problem of stopping - a problem, in case of which you cannot determine whether the program will run indefinitely or not. For example, in the event that Ethereum would not have provided for a payment system, then attackers could try to disrupt the network by performing an infinite loop inside the transaction, without incurring any losses. Thus, the payment system was introduced precisely to protect it from deliberate attacks.

It is likely that you will think: “And where am I?” Why should I pay for the use of storage? ”Well, what can I say, the entire network of Ethereum takes on itself the fee for both the calculations and the use of storage ... something like that.

Transactions and Messages

Earlier, I already wrote that Ethereum is a transaction state system. In other words, thanks to the transactions that take place between different accounts, the global state of Ethereum changes or moves from one state to another.

Simply put, a transaction is a cryptographically signed part of the instruction, which is first defined by the external account, and then ordered and transmitted to the blockchain.

In total, there are two types of transactions: sending messages and creating a contract (in other words, such transactions create new contracts in the Ethereum network).

All transactions contain the following elements, regardless of the type of the first:

  • nonce - the number of transactions that were sent by the sender.

  • gasPrice - the amount of Wei, which the sender is willing to give per unit of fuel required to complete the transaction.

  • gasLimit - the maximum amount of fuel that the sender is willing to pay for carrying out this transaction. This amount is set and paid in advance before any calculations are made.

  • to - the address of the recipient. At the time of the transaction associated with the creation of the contract, the account address of the contract does not yet exist, so an empty value is used instead.

  • value - the number of Wei to be transferred from the sender to the recipient. In transactions related to the creation of contracts, this value is the starting balance for the newly created account.

  • v, r, s - these symbols used to create a signature that identifies the sender of the transaction.

  • init - intended only for transactions related to the creation of contracts. An EVM code fragment used to initialize a newly created contract account. init is started only once and is not used later. When init is started for the first time, this element returns the body of the account code, which is the part of the code that is permanently associated with the contract account.

  • data is the input data (parameters) for a message call (data is an optional element that is intended only for message calls). For example, if a smart contract plays the role of a domain registration service, then a call to this contract may wait for input fields (for example, domain and IP address).

    From the information provided in the “Accounts” section, we found out that transactions — both for message calls and for creating contracts — are initiated by external accounts, and then redirected to the blockchain. In other words, transactions are a kind of bridge connecting the outside world and the internal state of the Ethereum platform.

    But this does not mean that some contracts can not interact with others: contracts that are in the global context of the state of Ethereum can interact with each other within this context. Their interaction or communication takes place by sending messages or internal transactions. The only difference between internal and ordinary transactions is that the first ones are not created by external accounts - but as a result of the creation of contracts. They are virtual objects which, unlike transactions, are not ordered and can exist only in the Ethereum execution environment.

When one of the contracts sends an internal transaction to another contract, a specific code is executed that exists in the recipient's contract account.


It is also worth noting that gasLimit is not provided for internal transactions or messages , since the fuel limit is set by the initiator of the initial transaction (for example, in an account). The fuel limit set by the external account must be high enough to complete the transaction, including any additional actions that are taken as a result of the transaction, such as sending a message from one contract to another. In the event that there is not enough fuel in the chain of transactions and messages to execute one of the latter, then its execution, as well as the execution of all subsequent messages caused by the initial execution, will be returned.

Blocks

All transactions are somehow grouped into “blocks”. The blockchain contains several such blocks interconnected.

Such blocks consist of:

  • block header

  • information about the series of transactions included in this block

  • a series of other block headers for current summers

What is ommer?

Let's understand what is ommer (from the English. «Ommer»). Ommer is a block whose parent is the parent element of the current block. In this chapter I will briefly describe what the ommerers are generally for, and also for what reasons the block contains block headers for ommeres.

Their presence, first of all, is justified by the fact that the blocking time in Ethereum is much lower (approximately 15 seconds) than for other blockchains, for example, for bitcoins (approximately 10 minutes). Thanks to this feature, the rate of conducting transactions increases. On the other hand, one of the negative sides of a shorter blocking time is that the mayner struggle for the next block solution is only intensifying. Such competing blocks are also called “blocks without a parent” (i.e., such blocks are not included in the main block chain).

Hommers were created so that miners could get a well-deserved reward for including blocks without parents in the main chain. Ommer, included by miners in the main chain, must be "valid": they, ommer, must be descendants in the sixth or earlier generation of the current block. For example, after the sixth generation, such descendants cannot be included in the main chain as blocks without a parent: later transactions may adversely affect the operation of the system as a whole.

For ommeres, you will receive a reward less than the inclusion of a full block. However, this should not detract from the miners' attempts to include such blocks without a parent and receive their well-deserved reward.

Block headers

I already mentioned earlier that each block has a title, but we didn’t understand what it is?

The block header is the part of the block that consists of:

  • parentHash - is a hash of the parent block header (so that, in fact, the block falls into the block chain)

  • ommersHash - hash of the current list of ommer blocks

  • beneficiary - the address of the account to which the payment is received for the inclusion of this unit

  • stateRoot - hash of the root node of the state of the prefix tree (I wrote earlier that the state of the prefix tree is stored in the header, thereby simplifying the state approval process for thin clients)

  • transactionsRoot - a hash of the root node of the prefix tree, containing all transactions that are listed in this block

  • receiptsRoot - hash of the root node of the prefix tree, which contains payment information for all transactions listed in this block

  • logsBloom - Bloom filter (data structure) consisting of information contained in logs

  • difficulty - the difficulty level of the current block

  • number - the current block number (the initial block has a number equal to zero; the block number is incremented by one for each subsequent block)

  • gasLimit - current fuel limit for current unit

  • gasUsed - the total amount of fuel used for transactions in the current block

  • timestamp - the timestamp intended to create the current block

  • extraData - additional data related to the current block

  • mixHash - a hash that, in combination with the nonce element, states that enough calculations are performed for the current block

  • nonce - a hash that, in combination with the mixHash element, states that enough calculations are performed for the current block

    It is worth noting that each block header contains three prefix tree structures for:

  • state ( stateRoot )

  • conducting transactions ( transactionsRoot )

  • getting information about payment ( receiptsRoot )

Such structures of the prefix tree are nothing but the prefix tree of Merkle, which we have already considered above.

In addition, for such a definition, there are several terms that you should probably find interesting.

Magazines

The Ethereum platform provides the ability to keep logs, the purpose of which is to record information about various transactions and messages. In addition, for the contract, it is also possible to openly create an entry in such a journal by declaring the “event” to be recorded.

The journal entry includes:

  • registrar's account address

  • a series of tasks that display various events performed for the current transaction

  • any data that are relevant to these events

Log entries are stored in Bloom Filter , which makes it possible to efficiently store an infinite amount of data.

Receiving payment information

Entries stored in the header come from information contained in the journal that relates to the transaction payment data (or check). Just as you receive a check when buying goods in a store, Ethereum creates a similar check for each of the transactions. And as you probably already guessed, each check contains information about the current transaction. The check includes:

  • block number

  • block hash

  • transaction hash

  • amount of fuel used for the current transaction

  • the total amount of fuel that was used to conduct the current transaction for a specific unit

  • log entries created by transaction

  • other information

Block complexity

Block complexity is a concept used to ensure the consistency of time that is needed to validate blocks. For the initial block, the difficulty is 131,072 units. A special formula is used to calculate the complexity of any of the blocks. In the event that the validation of one of the blocks occurred more quickly than, for example, the subsequent validation, then the protocol used in Ethereum increases the complexity of the latter.

The complexity of the block also affects the nonce hash, the execution of which is necessary during the display of the block, and the security check algorithms are used for this purpose.

The dependence of one parameter, block complexity, on the other, nonce, is represented in this formula:

where Hd is the block complexity.

The only way to determine the nonce parameter that will meet the condition presented by the formula is to use the health check algorithm to search for all of its possible values. The expected search time for all values ​​that meet this condition is the complexity of the block. Then we can conclude: the greater the block complexity value, the more difficult it is to find the nonce parameter, and thus the more difficult it is to validate the block, as a result of which, in turn, the time required for the validation of subsequent blocks increases. This means that, based on the value obtained during the block complexity determination, the protocol used determines how long it takes to validate the current block.

In that case, if the time required to validate a block is less than expected, then the protocol underestimates the complexity of the current block. Thus, the time required to validate a block is automatically set to continuously match the current parameters (on average, this time is 15 seconds).

Conducting transactions

Well, well, here we come to, perhaps, the most difficult part of the protocols used in Ethereum - conducting transactions. Let's imagine that you have set up a transaction on the Ethereum network. And what do you think will happen to the state of Ethereum during your transaction ?

First, any transaction must meet certain requirements in order for its execution not to be canceled, namely:

  • Transactions must meet RLP requirements. RLP is a recursive prefix length (from the English. Recursive Length Prefix), which is a data format that is used to encode nested arrays of binary data. The RLP format is used in Ethereum to organize objects.

  • The presence of a valid transaction signature.

  • Presence of valid nonce. Let me remind you that nonce is the number of transactions sent from the current account. In order for such a value to be valid, it must match the nonce value for the sender's account.

  • The fuel limit for a transaction must be equal to or greater than the specified amount of fuel. The specified amount of fuel includes:

  1. a predetermined cost of 21,000 units of fuel required to complete a transaction

  2. Fuel charge used to send transaction data (4 fuel units for each data byte or a code equal to zero and 68 for each non-zero data byte or non-zero code)

  3. Additional 32,000 units of fuel if the transaction is related to the conclusion of a contract

  • The balance of the current account of the sender must contain a sufficient amount of air to cover the "advance" cost of fuel, which the sender undertakes to pay. The advance cost of fuel is calculated as follows: the fuel cost limit is multiplied by the cost of fuel for the current transaction, with the result that we find the maximum cost of fuel. Further, the total amount of fuel transported from the sender to the recipient is added to the maximum cost.

    In the event that you have fulfilled all the above requirements, you proceed to the next step.

First of all, the advance cost of fuel is deducted from the sender’s account, and the sender’s nonce increases by 1. Then we can calculate the remaining amount of fuel using the following formula: we take away the specified amount of fuel from the total amount of fuel required for the transaction.

After that, the transaction starts. During the current transaction in the Ethereum is tracking "substate". A substate is required to record the information that was collected during the current transaction. Such information will be required immediately upon completion of the transaction and contains:

  • Self-destruct set : a set of accounts that will be deleted upon completion of the transaction

  • Log series : archived and indexed checkpoints needed to execute virtual machine code.

  • Refund balance : the amount to be returned to the sender upon completion of the transaction. I already mentioned earlier that using the storage provided by Ethereum costs a certain amount of money, and this money is returned to the sender after he stops using such storage. The Ethereum system stores information on the use of storage and return of funds for its use to the sender.

After this, the various calculations required for the transaction are performed.

After all the steps necessary to complete the transaction have been completed (assuming that all the above requirements have also been fulfilled), the status of the transaction is completed, and the amount of unused fuel to be returned to the sender is counted.

After the (successful) transaction is completed and the fuel is returned to the sender, the following occurs:

  • a certain amount of air used to purchase fuel is sent to the miner;

  • The fuel used to complete the transaction is recorded in a block for counting fuel (this block is used to store information about the total amount of fuel that was used to conduct all transactions in this block; in addition, this block is used during validation;

  • all account information contained in the self-destruct set section is deleted.

Here we are at the end of this chapter: we learned what a new state is and why we need a log for conducting transactions.

In the next chapter, we will take a closer look at the difference between the transactions related to creating contracts and sending messages.

Creating contracts

You probably remember that in Ethereum there are only two types of accounts: contract accounts and external ones. When you meet the term “contract related transactions”, you should be aware that the purpose of such a transaction is to create a new contract account.

To create a new contract account, we must first declare the address of the account being created using a special formula. After this, a new account is created. To perform such an operation, you must perform a series of actions:

  • set zero to nonce

  • adjust the balance of your account, equal to the payment for the transaction (in the event that the sender is ready to send a certain amount of air as payment for the transaction)

  • calculate the amount of payment that goes into the balance of the account created from the sender's account

  • indicate that the storage is no longer in use

  • configure contract hash code as empty string hash

At the moment when we started creating a new account, we, in fact, have already created it with the help of the init code , which is automatically sent at the beginning of the transaction (we forgot what the init code is - see the section “Transactions and Messages”). There are several scenarios during the execution of the init code (for example, it can happen: updating the storage for the account, creating another account for the current contract, sending a message, etc.).

After the system executes the code intended to create a new contract, fuel comes into play. You will not be able to conduct a transaction if it requires a greater amount of fuel than the one stored on your balance sheet. In the event that, despite such a restriction, you try to conduct a transaction, then you will receive a message about the lack of fuel, after which the system will automatically close. Moreover, if the completion of the transaction was caused due to a shortage of fuel, then you will be transferred to the stage prior to the transaction. And most importantly: the --recipient will not be refunded the amount of fuel that was spent before the discovery of its shortage--.

That's it…

However, if the sender has allocated a certain amount of air to conduct the current transaction, then this amount will be returned even if the creation of the contract is unsuccessful.

If the initialization code was successfully completed, the funds required to create the contract must be contributed by the creator. This amount also includes the cost of using storage, which is directly proportional to the increase in the size of the code created for the contract. In the event that the creator does not have enough funds to carry out this operation, then the transaction is terminated due to a shortage of fuel and the consequences will be the same as those listed above.

If everything went smoothly, and we did not receive a message about the lack of fuel, then all the unused fuel for this transaction is returned to the sender.

Victory!

Messages

The operation of sending a message, in general, is quite similar to the creation of a contract, not taking into account some small differences.

To perform this operation, the application of the init code is completely unnecessary, since as a result of its execution, a new account is not created. However, for such an operation you may need input data, but only if such data were transmitted by the recipient as a result of the transaction. After performing the operation on sending a message, a new block becomes available, containing output information, which is used when the operation is repeated.

Also, as in the case of creating a contract, if the sending operation was interrupted due to a shortage of fuel or an invalid transaction (for example, due to a stack overflow error, invalid transition address, incorrect command), the amount of fuel used for this operation is not returned call On the contrary, all unused fuel is also deducted from its balance, and the state of the system returns to the point preceding the balance transfer operation.

Until recently, Ethereum did not have the ability to interrupt or suspend transactions without losing the fuel you provided for such a purpose. For example, you can imagine a situation where you are the initiator of creating a contract, during the creation of which an error occurred, because the initiator of the call did not have the right to perform any of the transactions. So, in the previous version of Ethereum, before the platform was updated, in such a situation all the fuel remaining on your account would have been removed, and the sender would not have received his fuel back either. But with the release of the update - Byzantium - you have the opportunity to suspend the execution of operations to create contracts and return the system to its original state without losing the fuel remaining on your account. Thus, if the exit from the transaction occurred as a result of the suspension of its execution, the unused fuel is returned back to the sender.

Execution model

In the previous sections, I told you about how transactions are performed. Now, I suggest you deal with what is happening in the VM (from the English. Virtual Machine - virtual machine) at the time of the transaction.

The part of the protocol that performs transaction processing in the Ethereum operating system is called Ethereum Virtual Machine (VME) .

VME is a Turing machine, as mentioned in this article earlier. The only difference between a VME and a typical Turing machine is that the first one requires a virtual “fuel”. Thus, all calculations that can be performed in VME are somehow limited by the amount of fuel that is circulating in it, the virtual machine.

Source: CMU

In addition, VME has all the features of a stack architecture. A stack machine is a computer that uses the LIFO algorithm.

The size of any stack element in the VME is 256 bits, and the maximum stack size is 1024 bits.

For VME, a certain amount of memory is provided, which is not constant. Elements are stored in it as arrays of bytes with reference to words.

For VMEs, a specific storage area is also provided. Unlike the amount of memory, this storage (or storage area) does not change and is part of the system state. In VME, the program code is stored in a separate virtual ROM., access to which can be obtained only with the help of certain instructions. From this point of view, such a VME differs from the typical von Neumann architecture , in which the program code is stored in the computer's memory.

For VME also has its own special language - byte code VME. When a programmer, such as you or, for example, I, writes a smart contract that will be executed in the Ethereum system, this usually happens with the help of a high-level language, such as Solidity. After writing such a code, we compile it into the VME bytecode so that the VME can understand the command we wrote.

We proceed directly to the execution of operations.

Before you perform a specific calculation, the processor must verify that the following information is valid and accessible:

  • State of the system

  • Information about the amount of fuel required to perform the required operation

  • Address of the account that owns the executable code

  • Address of the sender of the transaction - the initiator of the current operation

  • Address of the account - the initiator of the executable code (may differ from the address of the sender-initiator)

  • Information on the amount of fuel required to complete a transaction

  • Input data for the operation

  • The number of Wei that should be sent to the account of this account as a result of the current operation

  • Information about running machine code

  • Block header information for the current block

  • Depth of the current message or contract creation

Immediately before the program starts, the system memory is absolutely empty, and the command counter is zero.

PC: 0 STACK: [] MEM: [], STORAGE: {}

After that, a recursive transaction begins in the VME: calculating the state of the system and the state of the machine for each cycle. The state of the system is the global state of Ethereum. Machine condition includes:

  • available amount of fuel;

  • command counter;

  • memory contents;

  • active word count in memory;

  • content stack

Elements of the stack are added or removed from the left edge of the code fragment.

For each cycle, a certain part of it is taken out of the remaining amount of fuel, and the command counter increases.

In total there are three possible options for the end of the cycle:

  1. The operations performed by the machine reach an exceptional state (for example, due to the lack of virtual fuel, incorrect instructions, insufficient number of stack elements, stack element values ​​exceeding 1024 bits, incorrect JUMP / JUMPI assignment) and, thus, the operation is suspended.

  2. The sequence of actions proceeds to the next cycle.

  3. The operations performed by the machine reach a logical conclusion (completion of the process)

If the calculations performed by the machine reach a logical conclusion, rather than an exceptional state, then as a result, the machine will issue the resulting state, as well as information about the remaining fuel and the resulting output data.

That's it. We have just learned the most complex and confusing part of Ethereum. Do not worry if you have not fully understood something: you do not need to delve into every detail and understand all the processes occurring in this system, well, if only you are not going to really fully study it and work at a sufficiently deep level.

The final design of the blocks

Let's finally figure out what happens to the blocks of transactions during their final clearance.

“Final design” can occur in two ways, depending on whether we are creating a block or it has already been created. In that case, if we only create a block, then the final design means the process of mining the current block. On the other hand, if a block has already been created, such a definition means the process of validating the current block. In both of the cases presented above, four conditions must be met for the final completion of the block.

  1. Validation (or, in the case of mining, the definition of) ommers: each block of ommers that is in the block header must have a valid block header and be the sixth descendant of the current block.

  2. Validation of transactions: the value of gasUsed for the current block should be equal to the value of the total amount of fuel used to carry out all the transactions listed in this block.

  3. Payment purpose (only in the case of mining): 5 units of ether are assigned to the beneficiary for mining each block (in accordance with the EIP-649 proposal, this payment will be reduced to 3 units of ether). Moreover, for each ommer, the beneficiary of the current block is charged as an additional 1/32 of the total payment for the current block. And the last thing: the beneficiary of the ommer block is also assigned a payment in the form of a certain amount, for the determination of which there is a special figure.

  4. Verification of the state and values ​​of nonce: To carry out this procedure, you need to ensure that all transactions are completed, as well as a change in the resulting states. After that, you will also need to set a new block after the payment for this block has been sent. The verification process occurs by comparing the trailing state with the state of the prefix tree stored in the header.

Mining, aimed at the proof of work

In the "Blocks" section, we briefly familiarized ourselves with such a concept as the complexity of the blocks. The algorithm by which the concept of block complexity has arisen is called Proof of Work (PoW).

The PoW algorithm used in the Ethereum system is called Ethash (previously, but called Dagger-Hashimoto).

This algorithm has the following form:

where m is mixHash; n is nonce; Hn is the header of the new block (nonce and mixHash are not included here, since these values ​​must be calculated); Hn - nonce for block header; d - DAG data set.

In the "Blocks" section, we also reviewed the various values ​​provided for the block header. These, as you remember, include values ​​such as mixHash and nonce. Once again I will remind:

  • mixHash is a hash that, together with the value of nonce, confirms that a sufficient number of calculations have been performed for the current block.

  • nonce is also a hash, which, together with the mixHash value, confirms that a sufficient number of calculations were performed for the current block.

Therefore, PoW is necessary to calculate the above values.

It is quite a difficult task to explain exactly how mixHash and nonce are calculated using the PoW function, and, in fact, a whole article can be devoted to this moment. But if in brief, the following happens:

The value of the "seed" is calculated for each of the blocks. To count each seed, there is its own "interval", with each interval being equal to 30,000 blocks. For each interval, the seed is a hash equal to a series of 32-byte zeros. For each subsequent interval, a specific hash hash is provided for the previous seed. Using this seed, the node finds the value of a pseudo-random hash.

Such a hash plays a very important role, since with its help we can better understand what the “thin nodes”, referred to in the previous articles, are. The goal of thin nodes is to provide an opportunity for some of the nodes to effectively check certain transactions without having to store the entire data set of the blockchain. A thin node can validate a transaction using only the given hash. This is due to the fact that this hash can re-create the block it needs for verification.

Using this hash, a node can create a DAG data packet in which each element depends on a small number of randomized pseudo-elements of the hash. Each novice miner must first create his full data packet. The system for each of the miners is stored a separate data packet, while the volume of such data is constantly growing.

For example, a miner can take any random parts from a data packet and use them in a mathematical function to hash such parts for mixHash. Such a miner will be able to constantly set the value for mixHash until the initial data is received as a nonce value. When this condition is fulfilled, such nonce value will be considered valid, and the block can be added to the circuit.

Mining as a defense mechanism

In general, the goal of PoW is to cryptographically prove that certain calculations were aimed at obtaining a certain result (nonce values). It just so happened that there is no other way to find a nonce, the value of which does not exceed a certain limit, except by using the enumeration of all possible options, including finding the required one. The distribution of output data for a constantly used function hash is evenly distributed. Thus, we know for sure that the time required to find a nonce value clearly depends on the complexity threshold : the higher the complexity threshold, the longer the search for the required nonce value will take place. The PoW algorithm represents the concept of complexity used in the blockchain under consideration.

What does safe blockchain mean? The answer is quite simple: a secure blockchain is a blockchain that ALL USERS will trust. As I wrote above, if there are more than two chains in the blockchain, then it is quite logical to assume that users will not feel confident while working with the blockchain, since no one will be able to say with accuracy which of the presented chains is valid.

The PoW algorithm is used precisely for this purpose: it ensures the unity of the chain in the blockchain, preventing the creation of other chains of blocks that may affect the transaction execution history(for example, creating fake transactions or deleting or modifying existing ones). Thus, in order for an attacker to be the first to validate his blocks, he will have to constantly determine the value of nonce, and do it faster than all other network users (I hope you remember the GHOST protocol, which I described earlier). Of course, for an attacker, such a method will not be feasible, unless it has at its disposal most of the mining resources of the network - such a scenario is known as a 51% attack .

Mining as a means of distributing finance

Apart from the fact that the PoW algorithm ensures the safe operation of the blockchain, it also distributes the remuneration to those users whose calculations were used to ensure security. I already wrote above that miners receive remuneration for the mining of a block, and also:

  • reward of 5 units of air for the "winning" block (soon this figure should drop to 3 units)

  • the cost of fuel consumed as a result of the transaction in the unit

  • additional remuneration for the inclusion of ommerov in the unit

In order to ensure the consistency of the PoW method - which is necessary to guarantee safety - and the distribution of remuneration Ethereum constantly adheres to the two principles below:

  • First, attract as many users as possible to use the platform. In other words, the use of this platform should not cause any difficulties for the user: he should not use any super-complex algorithms or use unknown hardware. In addition, the process of distribution of remuneration should also be clear and simple for everyone who is willing to expend some energy used by his computer for the sake of receiving several cherished units of ether.

  • Secondly, not to allow disproportionate distribution of rewards and other resources for any particular node: any such node for which an inappropriate distribution of resources is carried out will have a huge impact on the definition of the canonical blockchain, which negatively affects the security of the system as a whole.

For example, in the Bitcoin system there is a problem with the implementation of the above two principles: its PoW algorithm uses the SHA256 hash function. The problem of the latter is that its solution may be much easier if you use special hardware - ASICs.

In order to prevent such punctures in Ethereum, a special PoW algorithm with sequential memory is used ( Ethhash). the structure of the algorithm is constructed in such a way that a large amount of memory and a high throughput of the connection are required to calculate the nonce value. Requirements related to the presence of a large amount of memory imply that it will be very difficult for a computer with a standard memory size to perform a parallel calculation of several nonce values ​​simultaneously. As for high bandwidth requirements, even for a super-fast computer, detecting multiple nonce values ​​at the same time will be a daunting task. Thus, due to such features of this system, the probability of risk centralization is reduced and, moreover, more uniform conditions are created for the operation of various nodes performing verification.

By the way, not so long ago, I learned that Ethereum was going to switch from the PoW algorithm to a certain method called the “Proof of ownership” (from the English Proof-of-stake). Such a method in itself is worth a separate article for review and discussion.

Conclusion

Well, here we come to the logical conclusion of our article.

In fact, this article gives a lot of food for thought. You absolutely should not worry about it, if you have mastered this article from the second or third time. I personally re-read yellow paper and white paper for Ethereum many times before I began to delve into the essence of the matter.

I very much hope that this article was still useful for you. If you find any errors, I will be very grateful to you if you tell me about them.

Sources:

github.com/ethereum/yellowpaper
medium.com/@preethikasireddy/how-does-ethereum-work-anyway-22d1df506369

Sort:  

Congratulations @azok! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :

You published more than 10 posts. Your next target is to reach 20 posts.

Click here to view your Board
If you no longer want to receive notifications, reply to this comment with the word STOP

To support your work, I also upvoted your post!

Do not miss the last post from @steemitboard:

Carnival Challenge - Collect badge and win 5 STEEM
Vote for @Steemitboard as a witness and get one more award and increased upvotes!

Coin Marketplace

STEEM 0.18
TRX 0.16
JST 0.029
BTC 76262.49
ETH 2949.42
USDT 1.00
SBD 2.63