Ethereum Smart Contract Development
上QQ阅读APP看书,第一时间看更新

Turing completeness and the magic sauce

As we discussed in the previous section, Ethereum is a platform for decentralized applications. That means that we can write programs that can execute in a decentralized manner, where there is no central server or central entity that is going to execute our programs. The programs are going to be executed on many different computers, and this means that there is no way to take down such a decentralized application. In order to write such applications, we need to develop smart contracts, and smart contracts are written in a programming language called solidity. So, on the Ethereum blockchain, if you want to write a smart contract you need to learn solidity. Solidity is Turing complete. So, what does that mean? To understand this, we need to go back 60 or 70 years.

During that time, people had different calculation machines. The problem was that if you had a machine that could calculate something using one algorithm, then that machine could solve only that problem, and to solve another problem of a slightly different algorithmic construct, you had to build a separate machine from scratch.

So, Alan Turing, one of the greatest mathematicians and computer scientists of the 20th century, developed a logical design of a machine, a theoretical machine. He explained how such a machine could be built so that this machine could run any program.

In his theoretical explanation of this machine, you could build it using a simple tape, made of uniform cells, each storing 0 or 1 and a tape-head that could turn left or right by reading the tape-cells with an ability to store data. Basically he explained how you could build a computer that could run any program and solve any kind of computational problem. That being said, there was no guarantee how long this would take. Some programs could be executed in a minute, but some programs—for example, finding the solution to a problem based on prime numbers-could take thousands or several thousands of years. So, there was a guarantee that, sooner or later, the problem would be solved, but no guarantee how fast this would be. So, in theory, you could solve any computational problem on this Turing machine.

Nowadays, when we say that a particular programming language is Turing complete, we mean that by using that language we could implement any algorithm to solve any kind of computational problem. When a programming language is not Turing complete, it has many logical or syntactical restrictions that prevent it from formulating algorithms to solve certain kinds of computational problems.

For example, the scripting language used in bitcoin is not Turing complete. SQL from SQL92 standard is not Turing complete, whereas from SQL99 standard onwards it became Turing complete. Even big data tools like HiveQL and Pig Latin are not Turing complete. They become Turing complete only when they are supplemented by user defined functions (UDF) written in Java. On the other hand, PL/SQL, Java, JavaScript, Python, R, C, and C++ are all examples of Turing complete programming languages.

From a software developer's perspective, there is one important feature of a programming language which can quickly identify with sufficient accuracy whether that language is Turing complete or not. That feature is the ability to construct a programming loop. That means that if you have loops in your programming language, you can tell a program to do a set of instructions over and over again. This is what we have in solidity. Solidity has loops.

Vitalik Buterin usually explains Turing complete language as a programming language which can construct a loop, while scripting language of Bitcoin can only construct simple transaction logic and cannot construct a loop. So, if you want to do something a hundred times in the bitcoin scripting language, you would have to copy and paste the code a hundred times, while in Ethereum you could just write it once and tell the computer to execute it a hundred times.

For example, a simple computing device that has a loop and with an add operation can also be modified to do multiplication by looping a specific add operation; that is, 5 x 3 is equivalent to 5 + 5 + 5, which is equivalent to adding 5 with itself in 3 loops. However, it must be noted that loops are not always good for code performance, as loops within loops can exponentially increase the time complexity of any code. So, loops are good for identifying Turing completeness, but need to be avoided unless completely necessary, as they reduce code performance. We also have another problem of scalability, which will be addressed in later chapters, where we discuss the concept of sharding.

That is one of the prime reasons bitcoin avoided a Turing complete language. It was a decision by choice and not by mistake. You see, the whole idea of a Turing complete language running loops on a blockchain can be dangerous; because if you have a loop that executes some kind of code millions and millions of times, and this code has to be executed on a blockchain, it will really overload the network. That is why the developers of bitcoin decided not to use a Turing complete language. They just wanted a simple mechanism to get the basic job done, that is, to perform the transfer of values across peers. While in Ethereum, the design ideology is completely different with the introduction of complex DApps, which has to be executed using smart contracts on the Ethereum blockchain. Here, we absolutely need a Turing complete language, which must have looping constructs. Again, we cannot overload the Ethereum blockchain by running a million loops. So, we seem to be stuck in a catch-22 situation where loops are a necessary evil, the evil being blockchain overload and spamming other users.

This is the exact situation when we need a magic sauce; we call it gas in the Ethereum blockchain. Each operation done by solidity on the Ethereum blockchain has some fixed amount of gas fee associated with it. Let us go back to our brunch buffet analogy, where we talked about a gas burner for which developers/potluck chefs had to pay some fee to keep their DApps/recipes warm and palatable. You see, if I had to pay for gas burner fuel, I would automatically cook recipes that are good even on low gas usage, rather than recipes that require a lot of flames and constant high gas usage. So, rather than bringing hot kebabs, which need constant flames, I would bring something like a bread or bakery item, which require mild or no gas burner usage, to ensure I am not losing my money while waiting for someone to come and consume what I have cooked.

So, coming back to the Ethereum blockchain, if some rookie developer comes up with a super crazy program with millions of loops that could spam and overload the network, the gas cost will significantly increase for this programmer and his entire code will eventually stop executing once the gas purchased by the developer gets exhausted.

For example, if we run a code with five operations looping a 100 times, the gas fee would be consumed for each of the 500 loops. So, gas is that magic sauce, which needs to be purchased using ether (ETHtokens to run a solidity smart contract on an Ethereum blockchain. And yes, it is a prepaid model. You first buy some ether tokens using fiat money then, using these ether tokens you top-up your gas limit. Then, you run your smart contract program, which will continue to eat up gas from your account. The more efficient your code is, the less gas will be consumed by your code, the longer it can run on the blockchain, and the better your DApps will be to your clients.

It is crucial to differentiate between gas and ether in an Ethereum blockchain. As discussed earlier, gas is a sort of fee to run smart contract operations on an Ethereum blockchain, whereas ether is the cryptocurrency token on the Ethereum blockchain. A good real-life analogy would be petrol or diesel for driving a car. To drive a car on the highway, we need to fill it with petrol or diesel. We need plain cash, credit/debit cards, or e-wallet money to buy the petrol or diesel. Now, it really depends on the internal mechanics of the car, the weather conditions, the road and traffic conditions, the way we drive, and many such parameters, which affect the consumption of fuel per unit of miles travelled. We call it the mileage and this parameter determines the performance of the car. Again, the fuel price can fluctuate due to a change in international market conditions and its effect on the value of fiat currency. On the same lines, if the car is the solidity smart contract code, gas is the fuel used to fill up the car to make it run on the highway of a blockchain. We purchase this gas using ether, where ether is equivalent to our real-world fiat currency.

Figure 2.13 illustrates the scale of unit on an Ethereum blockchain and the ETH equivalent value in fiat money in present money:

Figure 2.13: Ether on money market along with units in an Ethereum blockchain

A genuine concern now arises that we can never know how my smart contract code will perform on a blockchain unless we run it. For that reason, the Ethereum platform has introduced the concept of testnet and mainnet. Once we code our solidity smart contracts, we can run them on testnet and check how much operations are costing in terms of gas fee, but in a virtual setting; that is, we can run the code for free to simulate the gas fee amount. Once we are satisfied with the gas consumption rate and efficiency of our smart contract code, we deploy it as the final code into the mainnet where the code gets engraved permanently into the Ethereum blockchain. The earlier testnet was called the morden, and was scrapped due to security issues. The current testnet is called the Ropsten.

So, we see that smart contracts are more than mere transactions representing transfer of values. A natural question arises about whether the block architecture of bitcoin is sufficient for Ethereum? Moreover, how do we mine in an Ethereum blockchain? And why do we have two separate cryptocurrency tokens ETH and ETC? Let us find out in the next section.