Original:lottery secretsJoin us
Translator: Feilong
Protocol: CC BY-NC-SA 4.0
Blockchain is a decentralized ledger that maintains a continuously growing list of data records, protected from tampering and revision. Each user can connect to the network, send new transactions, verify transactions, and create new blocks.
This book will teach you what blockchain is, how it maintains data integrity, and how to create real-world blockchain projects using Ethereum. Through interesting real-world projects, you will learn how to write smart contracts, which are programmed entirely and have no opportunities for fraud, review, or third-party intervention, and build end-to-end blockchain applications. You will learn about cryptographic concepts in cryptocurrencies, Ethereum security, mining, smart contracts, and Solidity, among other concepts.
Blockchain is the main technological innovation of Bitcoin, serving as the public ledger for Bitcoin transactions.
Chapter 1, Understanding Decentralized Applications, will explain what DApps are and outline their working principles.
Chapter 2, Understanding How Ethereum Works, explains the working principle of Ethereum.
Chapter 3, Writing Smart Contracts, shows how to write smart contracts and how to deploy and broadcast transactions using web3.js in the interactive console of geth.
Chapter 4, Getting Started with web3.js, introduces web3js, how to import and connect to geth, and explains how to use it in Node.js or client-side JavaScript.
Chapter 5, Building a Wallet Service, explains how to build a wallet service where users can easily create and manage Ethereum wallets, even offline. We will specifically use the LightWallet library to achieve this.
Chapter 6, Building a Smart Contract Deployment Platform, demonstrates how to compile smart contracts using web3.js and deploy them using web3.js and EthereumJS.
Chapter 7, Building a Betting Application, explains how to use Oraclize to send HTTP requests from Ethereum smart contracts to access data from the World Wide Web. We will also learn how to access files stored in IPFS, handle strings using string libraries, and so on.
Chapter 8, Building Enterprise-level Smart Contracts, explains how to easily build enterprise-level DApps using Truffle. We will learn Truffle by building an alternative currency.
Chapter 9, Building a Consortium Chain, we will discuss consortium chains.
You need Windows 7 SP1+, 8, 10, or Mac OS X 10.8+.
This book is suitable for JavaScript developers who want to use blockchain and Ethereum to create tamper-proof data (and transaction) applications. Those interested in cryptocurrencies, the logic and databases that support them, will find this book very useful.
In this book, you will find many text styles to distinguish different types of information. Here are some examples of these styles and their explanations.
The code words, database table names, folder names, file names, file extensions, path names, virtual URLs, user inputs, and Twitter handles are displayed as follows: ‘Then, run the application using the command in the directory.’
Code blocks are set up as follows:
Any command line input or output is as follows:
New terms and important vocabulary are displayed in bold. For example, the words seen on the screen, such as menu or dialog box words, are displayed in the text as follows: ‘Now select the same file again, then click the ‘Get Information’ button.’
Warnings or important tips will appear in this box.
Tips and tricks will appear in this way.
Almost all internet applications we have been using are centralized, that is, each application’s server is owned by a specific company or individual. Developers have been building centralized applications, and users have been using them for a long time. However, centralized applications have some issues that make it almost impossible to build certain types of applications, and each application will eventually have some common problems. Some problems with centralized applications are less transparent, have a single point of failure, and fail to prevent network censorship, etc. Due to these problems, a new technology has emerged for building internet-based applications, known as decentralized applications (DApps). In this chapter, we will learn about decentralized applications.
In this chapter, we will cover the following topics:
What is a DApp?
What is the difference between decentralized, centralized, and distributed applications?
Advantages and disadvantages of centralized and decentralized applications
An overview of the data structures, algorithms, and protocols used by some of the most popular DApps
Get to know some popular DApps built on top of other DApps.
DApp is an internet application that runs on a decentralized peer-to-peer network, with its source code being open source. No single node in the network has complete control over the DApp.
According to the different functions of DApps, different data structures are used to store application data. For example, the Bitcoin DApp uses the blockchain data structure.
These peers can be any computer connected to the internet; therefore, detecting and preventing peers from making invalid changes to application data and sharing erroneous information with others becomes a major challenge. Therefore, we need to reach a consensus among peers on whether the published data is correct or incorrect. In DApps, there is no central server to coordinate peers and decide what is right and what is wrong; therefore, overcoming this challenge becomes very difficult. There are some protocols (known as consensus protocols) to address this challenge. Consensus protocols are specifically designed data structures for DApp use. For example, Bitcoin uses the Proof of Work protocol to reach consensus.
Each DApp requires a client for users to use. To use a DApp, we first need to connect the client to the node server by running our own node server. The nodes of DApps provide an API and allow the developer community to use the API to develop various clients. Some DApp developers officially provide clients. The clients of DApps should be open source and should be downloadable for use; otherwise, the entire concept of decentralization will fail.
However, the client architecture setup is cumbersome, especially for non-developer users; therefore, the client is usually hosted, and/or nodes are hosted as a service to make the process of using DApps simpler.
What are distributed applications?
Distributed applications are those that are distributed across multiple servers rather than just one. When application data and traffic become massive and the downtime of the application is unacceptable, distributed applications must be adopted. In distributed applications, data is replicated between servers to achieve high availability. Centralized applications may be distributed or not, but decentralized applications are always distributed. For example, Google, Facebook, Slack, Dropbox, etc., are distributed, while simple portfolio websites or personal blogs are usually distributed only when there is a high traffic.
The following are some of the advantages of decentralized applications:
DApps have fault tolerance because they are distributed by default and have no single point of failure.
They can prevent the intrusion of network censorship because there is no central authority that can be pressured by the government to remove some content. The government even cannot block the domain name or IP address of the application because DApps are not accessed through specific IP addresses or domain names. Clearly, the government can trace individual nodes in the network through IP addresses and shut them down, but if the network is very large, it becomes almost impossible to shut down the application, especially if the nodes are distributed in different countries.
Users easily trust the application because it is not controlled by a single authoritative body that may deceive users for profit purposes.
Clearly, every system has its own advantages and disadvantages. The following are some of the disadvantages of decentralized applications:
It is very difficult to fix errors or update DApps because each peer in the network must update its node software.
Some applications require user identity verification (i.e., KYC), and due to the lack of a central authority to verify user identity, it becomes a problem when developing such applications.
They are difficult to build because they use very complex protocols to achieve consensus and must be built from the beginning to accommodate scale. Therefore, we cannot just implement an idea and then add more features and expand it later.
Applications usually operate independently of third-party APIs to retrieve or store content. DApps should not rely on centralized application APIs, but they may depend on other DApps. Since there is no large DApps ecosystem yet, building DApps is very difficult. Although theoretically DApps may depend on other DApps, in practice, tightly coupled DApps are very difficult to achieve.
Generally, signed documents represent organizations and have influence from the government. Depending on the type of organization, it may or may not have shareholders.
A Decentralized Autonomous Organization (DAO) is an organization represented by a computer program (that is, the organization operates according to the rules written in the program), is completely transparent, is fully controlled by shareholders, and is not affected by the government.
To achieve these goals, we need to develop a DAO as a DApp. Therefore, we can say that DAO is a subclass of DApp.
Dash and DAC are examples of several DAOs.
What is a Decentralized Autonomous Corporation (DAC)? There is still no clear distinction between DACs and DAOs. Many people think they are the same, while some define DACs as DAOs when DAOs are intended to make a profit for shareholders.
One of the main advantages of DApps is that they usually guarantee user anonymity. But many applications require user identity verification to use the application. Since there is no central authority in DApps, verifying user identity becomes a challenge.
In centralized applications, people verify user identity by asking users to submit certain scanned documents, OTP verification, and other methods. This process is known as Know Your Customer (KYC). However, in DApps, no one verifies user identity, and DApps must verify user identity on their own. Clearly, DApps cannot understand or verify scanned documents, nor can they send SMS messages; therefore, we need to provide them with digital identities that they can understand and verify. The main problem is that almost no DApps have digital identities, and only a few people know how to obtain digital identities.
Digital identities come in various forms. Currently, the most recommended and popular form is the digital certificate. A digital certificate (also known as a public key certificate or identity certificate) is an electronic document used to prove ownership of a public key. Essentially, users have a private key, a public key, and a digital certificate. The private key is secret and should not be shared with anyone. The public key can be shared with anyone. The digital certificate contains the public key and information about who owns the public key. Clearly, it is not difficult to generate such certificates; therefore, digital certificates are always issued by authorized entities that you can trust. The digital certificate has a field encrypted with the private key of the certificate authority. To verify the authenticity of the certificate, we simply need to decrypt this field using the public key of the certificate authority, and if the decryption is successful, we know that the certificate is valid.
Even if users successfully obtain digital identities and they are verified by DApps, there is still a major issue; that is, there are various digital certificate authorities, and to verify digital certificates, we need the public key of the issuing authority. It is very difficult to include the public keys of all issuing authorities and update/add new public keys. Due to this problem, digital identity verification programs are usually included in the client to facilitate easy updates. Moving this verification program to the client does not completely solve the problem, because there are many institutions issuing digital certificates, and tracking all institutions and adding them to the client is cumbersome.
Why don’t users verify each other’s identity?
In real-life transactions, we usually verify the identity of the other party ourselves or ask an authoritative body to verify the identity. This idea can also be applied to DApps. Users can manually verify the identity of each other before making transactions. This idea is suitable for certain types of DApps, those in which people trade with each other. For example, if a DApp is a decentralized social network, it is obviously not possible to verify profiles in this way. But if a DApp is used for buying and selling things, both the buyer and the seller can verify the identity of the other party before making payment. Although this idea seems good in transactions, actually thinking about it will find that it becomes very difficult, because you may not want to verify identity every time you make a transaction, and not everyone knows how to verify identity. For example, if a DApp is a ride-sharing application, it is obviously not desirable to verify identity every time you book a vehicle. But if you occasionally make transactions and know how to verify identity, following this process is acceptable.
Due to these issues, our only option at present is for authorized personnel of the company providing the client to manually verify user identity. For example, no identity verification is required when creating a Bitcoin account, but when transferring Bitcoin to fiat currency, the exchange will require identity verification. Clients can ignore unverified users and not allow them to use the client. They can keep the client open for users whose identity has been verified by them. This solution also has some minor issues; that is, if you change clients, you will not be able to find the same group of users to interact with, because different clients have different sets of verified users. For this reason, all users may decide to use only one specific client, thus creating a monopoly between clients. But this is not a major problem, because if the client fails to verify users correctly, users can easily switch to another client without losing critical data, as it is stored in a decentralized manner.
The idea of verifying user identity in an application is to make it difficult for users to escape after performing some fraudulent activities, prevent users with fraudulent/criminal backgrounds from using the application, and provide a means for other users in the network to believe the identity claimed by the user. Regardless of what program is used to verify user identity, users always have a way to represent themselves as someone else. Whether we use digital identity or scan documents for verification is irrelevant, as both can be stolen and reused. The important thing is to make it difficult for users to represent themselves as someone else and collect enough data to track users and prove that they have engaged in fraudulent activities.
Many applications require the functionality of user accounts. Data related to accounts should only be modified by the account owner. DApps cannot have account functionality based on usernames and passwords like centralized applications because passwords cannot prove that the change of account data is requested by the owner.
There are many ways to implement user accounts in DApps. But the most popular method is to use public and private key pairs to represent accounts. The hash of the public key is the unique identifier of the account. To change account data, the user needs to sign the change using their private key. We need to assume that users will safely store their private keys. If users lose their private keys, they will never be able to access their own accounts.
Due to single points of failure, DApps should not depend on centralized applications. But in some cases, there is no choice. For example, if a DApp wants to read football scores, where will it obtain the data? Although a DApp can depend on another DApp, why would FIFA create a DApp? FIFA would not create a DApp just because other DApps need data. This is because a DApp providing scores is of no benefit because it will ultimately be completely controlled by FIFA.
In some cases, DApps need to obtain data from centralized applications. But the main problem is how DApps can know that the data obtained from the domain has not been tampered with by intermediate services or people, but is the actual response. Well, according to the architecture of DApps, there are various solutions. For example, in Ethereum, for smart contracts to access centralized APIs, they can use Oraclize services as intermediaries because smart contracts cannot make HTTP requests directly. Oraclize provides TLSNotary proof for the data obtained by smart contracts from centralized services.
For a centralized application to maintain its long-term operation, the owner of the application needs to make a profit to keep it running. DApps do not have owners, but like any other centralized application, the nodes of DApps require hardware and network resources to maintain their operation. Therefore, the nodes of DApps need to receive some useful rewards to maintain the operation of DApps. This is where internal currency comes into play. Most DApps have built-in internal currency, or we can say that most successful DApps have built-in internal currency.
The consensus protocol determines how much currency a node can obtain. According to the consensus protocol, only certain types of nodes can obtain currency. We can also say that nodes contributing to the secure operation of DApps are the nodes that obtain currency. Nodes that only read data will not receive any rewards. For example, in Bitcoin, only miners who successfully mine blocks can obtain Bitcoin.
The biggest question is, why would anyone value it given that this is a lottery and How to find it? Well, from an economic perspective, anything that is in demand but has insufficient supply will have value.
Using internal currency to allow users to pay for using DApps can solve the demand problem. As more and more users use DApps, demand will also increase, and the value of the internal currency will also increase accordingly.
Setting a fixed number of producible currencies makes the currency scarce, thereby increasing its value.
Money is supplied over time rather than in one go. This is done so that new nodes entering the network can also maintain the safe operation of the network and obtain money.
The only drawback to having an internal currency in DApps is that DApps are no longer free to use. This is one of the advantages that centralized applications have, because centralized applications can profit from advertisements, provide advanced APIs for third-party applications, and can offer services for free to users.
In DApps, we cannot integrate advertisements because no one checks the ad standards; clients may not display ads because there is no benefit for them to do so.
Until now, we have been learning about completely open and permissionless DApps; that is, anyone can participate without establishing an identity.
On the other hand, permissioned DApps do not open participation to everyone. Permissioned DApps inherit all the attributes of permissionless DApps, except that you need to obtain a permit to participate in the network. The permit systems between permissioned DApps vary.
To join a permissioned DApp, you need to obtain a permit, so the consensus protocol of permissionless DApps may not be very effective in permissioned DApps; therefore, they have a consensus protocol different from that of permissionless DApps. Permissioned DApps do not have an internal currency.
Now that we have a high-level understanding of what DApps are and how they differ from centralized applications, let’s explore some popular and useful DApps. When exploring these DApps, we will delve sufficiently deep to understand their working principles and address various issues, rather than going into too much detail.
Bitcoin is a decentralized currency. Bitcoin is the most popular DApp, and its success showcases how powerful DApps can be, encouraging people to build other DApps.
Before we delve into the working principle of Bitcoin and why people and governments believe it to be a currency, we need to understand what a ledger and a blockchain are.
The ledger is essentially a list of transactions. Databases are different from ledgers. In the ledger, we can only append new transactions, while in databases, we can append, modify, and delete transactions. Databases can be used to implement ledgers.
The blockchain is a data structure used to create a decentralized ledger. The blockchain is composed of blocks in a sequential manner. A block contains a set of transactions, the hash of the previous block, a timestamp (indicating the creation time of the block), block reward, block number, and so on. Each block contains the hash of the previous block, thereby creating a linked blockchain. Each node in the network stores a copy of the blockchain.
Proof of Work, Proof of Stake, and other consensus protocols are used to maintain the security of the blockchain. Depending on the consensus protocol, blocks are created and added to the blockchain in different ways. In Proof of Work, blocks are created through a process called mining, which can maintain the security of the blockchain. In Proof of Work protocols, mining involves solving complex puzzles. We will learn more about blockchain and its consensus protocols in detail later in this book.
The blockchain in the Bitcoin network stores Bitcoin transactions. New bitcoins are supplied to the network by issuing new bitcoins to the nodes that successfully mine blocks.
The main advantage of the blockchain data structure is automated auditing and making applications transparent and secure. It can prevent fraud and corruption. Depending on how you implement and use it, it can be used to solve many other problems.
Firstly, Bitcoin is not an international currency; rather, it is a decentralized currency. International currencies are mostly legal because they are an asset, and their use is evident.
The main issue is whether DApps that only use currency are legal. The straightforward answer is that they are legal in many countries. Only a few countries have made them illegal, while most have not decided.
This is why some countries have made it illegal while most have not decided:
Due to identity issues in DApps, user accounts in Bitcoin have no associated identity, so it can be used for money laundering.
These Online casino and How to find it are very volatile, so the risk of losing money is greater.
When using Online casino and How to find it, tax evasion is really easy.
The Bitcoin network is only used for sending/receiving Bitcoin, and nothing else. So you might wonder why anyone would have a need for Bitcoin.
The following are some of the reasons why people use Bitcoin:
The main advantage of using Bitcoin is that it makes sending and receiving payments anywhere in the world simple and quick.
Online payment transaction fees are expensive compared to Bitcoin transaction fees.
Hackers can steal your payment information from merchants, but in the case of Bitcoin, stealing a Bitcoin address is completely useless because in order for a transaction to be valid, it must be signed using its associated private key, and users do not need to share their private keys with anyone to make payments.
Ethereum is a decentralized platform that allows us to run DApps on it. These DApps are written using smart contracts. One or more smart contracts can form a DApp together. Ethereum smart contracts are programs that run on Ethereum. Smart contracts will run according to the precise program at the time of programming, with no possibility of downtime, audits, fraud, and interference from third parties.
The main advantage of running smart contracts on Ethereum is that it makes interactions between smart contracts easier. Moreover, you don’t have to worry about integrating consensus protocols and other transactions; instead, you just need to write application logic. Clearly, you cannot use Ethereum to build any type of DApp; you can only build DApps that are supported by the features of Ethereum.
Ethereum has an internal currency called Ether. To deploy smart contracts or execute functions of smart contracts, you need Ether.
This book is dedicated to building DApps using Ethereum. In this book, you will delve deeply into every aspect of Ethereum.
Hyperledger is a project dedicated to building technology for building licensed DApps. Hyperledger fabric (abbreviated as fabric) is an implementation of the Hyperledger project. Other implementations include Intel Sawtooth and R3 Corda.
Fabric is a licensed decentralized platform that allows us to run licensed DApps (known as chaincode) on it. We need to deploy our own Fabric instance and then deploy our licensed DApps on it. Each node in the network runs an instance of Fabric. Fabric is an easy-to-plug-and-play system, allowing you to easily plug and unplug various consensus protocols and features.
Hyperledger uses blockchain data structures. Blockchain based on Hyperledger can currently choose not to use a consensus protocol (i.e., NoOps protocol), or use the PBFT (Practical Byzantine Fault Tolerance) consensus protocol. It has a special node called a certificate authority, which controls who can join the network and what they can do.
IPFS (InterPlanetary File System) is a decentralized file system. IPFS uses DHT (Distributed Hash Table) and Merkle DAG (Directed Acyclic Graph) data structures. It uses a protocol similar to BitTorrent to determine how data is moved within the network. One advanced feature of IPFS is that it supports file version control. To implement file version control, it uses data structures similar to Git.
Although it is called a decentralized file system, it does not follow a major attribute of file systems; that is, when we store something in a file system, it guarantees that it will exist until it is deleted. But IPFS does not operate this way. Each node does not save all files; it stores the files it needs. Therefore, if a file is not popular, it is obvious that many nodes will not have it; therefore, the file has a high possibility of disappearing from the network. Therefore, many people prefer to call IPFS a decentralized peer-to-peer file sharing application. Or, you can view IPFS as a completely decentralized BitTorrent; that is, it has no trackers and some advanced features.
Let’s take a look at an overview of how IPFS works. When we store a file in IPFS, it is divided into blocks smaller than 256 KB, and a hash value is generated for each block. Nodes in the network save the IPFS files they need and their hash values in a hash table.
IPFS files have four types: blob, list, tree, and commit. Blob represents the actual file blocks stored in IPFS. List represents a complete file because it saves a list of blobs and other lists. Since lists can contain other lists, it helps with data compression over the network. Tree represents a directory because it saves a list of blobs, lists, other trees, and commits. The commit file represents a snapshot in the version history of any other file. Since lists, trees, and commits have links to other IPFS files, they form a Merkle DAG.
Therefore, when we want to download a file from the network, we only need the hash of the IPFS list file. Or, if we want to download a directory, we only need the hash of the IPFS tree file.
Since each file is identified by a hash value, the names are not easy to remember. If we update a file, we need to share a new hash value with everyone who wants to download the file. To solve this problem, IPFS uses the IPNS feature, which allows self-certifying names or human-readable names to point to IPFS files.
The main reason preventing IPFS from becoming the primary decentralized file system is that nodes only store the files they need. Filecoin is a decentralized file system similar to IPFS, with an internal currency to incentivize nodes to store files, thereby improving file availability and making it more like a file system.
Nodes in the network will earn Filecoins to rent disk space, and you need to spend Filecoins to store/retrieve files.
In addition to the IPFS technology, Filecoin uses blockchain data structures and the retrievability proof consensus protocol.
At the time of writing this article, Filecoin is still under development, so many things are still unclear.
Namecoin is a decentralized key-value database. It also has an internal currency called Namecoins. Namecoin uses the blockchain data structure and the proof of work consensus protocol.
In Namecoin, you can store key-value pair data. To register a key-value pair, you need to spend Namecoins. Once registered, you need to update it every 35,999 blocks; otherwise, the value associated with the key will expire. To update, you also need Namecoins. There is no need to update the key; that is to say, after registering the key, you do not need to spend any Namecoins to retain the key.
Namecoin has namespace functionality that allows users to organize different types of keys. Anyone can create a namespace or use an existing namespace to organize keys.
Some of the most popular namespaces include (application-specific data), (domain specification), (secure domain), (identity), (secure identity), (product), and so on.
To access a website, the browser first needs to find the IP address associated with the domain. The mapping of these domain names and IP addresses is stored in DNS servers, controlled by large companies and governments. Therefore, domain names are susceptible to censorship. If a website engages in illegal activities, causes losses to them, or for other reasons, governments and companies usually block the domain name.
Therefore, it is necessary to establish a decentralized domain name database. Since Namecoin stores key-value data like DNS servers, it can be used to implement a decentralized DNS, which has already been applied. The d and ds namespaces contain keys ending with ., representing domain names. Technically, there are no naming conventions for keys in the namespace, but all Namecoin nodes and clients agree on this naming convention. If we try to store invalid keys in the and namespaces, the client will filter out the invalid keys.
Browsers that support domains need to look up the IP address associated with the domain in the Namecoin namespace and domain name.
The difference between the namespace and the domain name is that the namespace stores domains that support TLS, while the domain name stores domains that do not support TLS. We have already decentralized the DNS; similarly, we can also decentralize the issuance of TLS certificates.
This is how TLS works in Namecoin. Users create self-signed certificates and store the certificate hash in Namecoin. When a client supporting the domain tries to access a secure domain, it will match with the certificate hash returned by the server, and if it matches, it will continue to communicate further with the server.
The decentralized DNS formed by Namecoin is the first solution of Zooko’s Triangle. Zooko’s Triangle defines applications with three properties, namely decentralized, identity, and security. Digital identity is not only used to represent a person but can also represent a domain, company, or other things.
Dash is a decentralized currency similar to Bitcoin. Dash uses blockchain data structures and the proof-of-work consensus protocol. Dash solves some of the major problems caused by Bitcoin. The following are some of the issues related to Bitcoin:
Transactions require a few minutes to complete, and in today’s world, we need transactions to be completed immediately. This is because the mining difficulty in the Bitcoin network is adjusted to create an average of one block every 10 minutes. We will learn more about mining later in this book.
Although the account does not have an associated identity, the exchange of Bitcoin for real currency or the purchase of things with Bitcoin is traceable; therefore, these exchanges or merchants can disclose your identity to the government or other institutions. If you run your own node to send/receive transactions, then your ISP can see the Bitcoin address and trace the owner using the IP address, because broadcast messages in the Bitcoin network are not encrypted.
Dash aims to solve these problems by making transactions almost instant and by not identifying the real person behind the real account. It also prevents your ISP from tracking you.
In the Bitcoin network, there are two types of nodes, namely miners and ordinary nodes. However, in Dash, there are three types of nodes, namely miners, main nodes, and ordinary nodes. The main nodes are what make Dash so special.
To host a main node, you need to own 1,000 Dash and a static IP address. In the Dash network, both main nodes and miners earn Dash. When a block is mined, 45% of the reward goes to the miners, 45% to the main nodes, and the remaining 10% is used for the budgeting system.
The main nodes implement decentralized governance and budgeting. Due to the decentralized governance and budgeting system, Dash is called DAO because it indeed is.
The main nodes in the network are like shareholders; they have the right to decide the destination of 10% of Dash. This 10% of Dash is usually used to fund other projects. Each main node has the right to use one vote to approve a project.
The discussion of the project proposal occurs outside the network. However, the voting takes place within the network.
Main nodes can provide possible solutions for user authentication in DApps; that is, main nodes can democratically select a node to verify user identity. The person or entity behind this node can manually verify user files. Partial rewards can also be given to this node. If the node cannot provide good service, the main node can vote to elect another node. This can be a good solution for a decentralized identity issue.
Main nodes are not just for approving or rejecting proposals; they also constitute a service layer that provides various services. The reason main nodes provide services is that the more services they provide, the more functional the network becomes, thereby increasing the number of users and transactions, which in turn increases the price of Dash currency and block rewards, thus helping main nodes earn more profits.
Main nodes provide services such as PrivateSend (providing anonymous coin mixing services), InstantSend (providing nearly instant transaction services), DAPI (providing a decentralized API so that users do not need to run a node), and more.
At any given time, only 10 main nodes are selected. The selection algorithm uses the current block hash to select main nodes. We then request services from them. Responses received from the majority of nodes are considered correct. This is how consensus is achieved on the services provided by the main nodes.
The service proof consensus protocol is used to ensure that the main nodes are online, responsive, and that their blockchain is up to date.
BigChainDB allows you to deploy your own permissioned or permissionless decentralized database. It uses blockchain data structures as well as various other database-specific data structures. As of the time of writing this article, BigChainDB is still under development, so many things are still unclear.
It also provides many other features, such as rich permissions, queries, linear scaling, and local support for multi-asset and alliance consensus protocols.
OpenBazaar is a decentralized e-commerce platform. You can buy or sell goods using OpenBazaar. In the OpenBazaar network, users are not anonymous because their IP addresses are recorded. A node can be a buyer, seller, or arbitrator.
It uses a Kademlia-style distributed hash table data structure. Sellers must host a node and keep it running to make goods visible in the network.
It prevents account spam by using the proof-of-work consensus protocol. It uses proof-of-burn, CHECKLOCKTIMEVERIFY, and secure deposit consensus protocols to prevent spam in ratings and comments.
Buyers and sellers use Bitcoin for transactions. Buyers can add an arbitrator when purchasing goods. The arbitrator is responsible for resolving any disputes that arise between buyers and sellers. Anyone can become an arbitrator in the network. Arbitrators earn commissions by resolving disputes.
Ripple is a decentralized remittance platform. It allows us to transfer fiat currencies, lottery and How to find it, and commodities. It uses blockchain data structures and has its own consensus protocol. In Ripple’s documentation, you will not find the terms blocks and blockchain; they use the term ledger instead.
In Ripple, the transfer of currencies and commodities is done through a trust chain, similar to the operation of the hawala network. In Ripple, there are two types of nodes, namely gateways and regular nodes. Gateways support the deposit and withdrawal of one or more currencies and/or commodities. To become a gateway in the Ripple network, you need to obtain a gateway permit to form a trust chain. Gateways are usually registered financial institutions, exchanges, merchants, and so on.
Each user and gateway has an account address. Each user needs to add the addresses of the gateways they trust to their trust list. There is no consensus on who to trust; it is entirely up to the user, and the user assumes the risk of trusting the gateway. Even gateways can add their trusted gateways to their list.
Let’s look at an example, where user X lives in India and wants to send 500 US dollars to user Y who lives in the United States. Suppose there is a gateway named XX in India that accepts cash (either physical cash or card payments on the website) and only gives you Indian rupees on Ripple. X will visit the office or website of XX, deposit 30,000 Indian rupees, and then XX will broadcast a transaction indicating that I owe X 30,000 Indian rupees. Now suppose there is a gateway named YY in the United States that only allows dollar transactions, and Y trusts the YY gateway. Now, suppose that gateway XX and YY do not trust each other. Since X and Y do not trust a common gateway, XX and YY do not trust each other, and ultimately XX and YY do not support the same currency. Therefore, for X to send funds to Y, he needs to find an intermediary gateway to form a trust chain. Suppose there is another gateway ZZ that is trusted by XX and YY and supports both US dollars and Indian rupees. Therefore, now X can send a transaction by transferring 50,000 Indian rupees from XX to ZZ, and ZZ will convert it to US dollars, then ZZ will send the funds to YY, asking YY to hand over the funds to Y. Now, rather than saying X owes Y 500 US dollars, it is more accurate to say that YY owes Y 500 US dollars, ZZ owes YY 500 US dollars, and XX owes ZZ 30,000 Indian rupees. But that’s all right, because they trust each other, while X and Y did not trust each other before. However, XX, YY, and ZZ can transfer funds outside of Ripple at any time, otherwise, the reverse transaction will deduct this value.
Ripple also has an internal currency called XRP (or ripple). Every transaction sent to the network consumes some ripples. Since XRP is the local currency of ripples, it can be sent to anyone in the network without trust. XRP can also be used when forming a trust chain. Remember, each gateway has its own currency exchange rate. XRP is not generated through a mining process; instead, a total of 100 billion XRP were generated at the beginning and owned by the ripple company. XRP is manually provided based on various factors.
All transactions are recorded in a decentralized ledger, forming an immutable history. Consensus is required to ensure that all nodes have the same ledger at a particular point in time. In Ripple, there is also a third type of node called a validator, which is part of the consensus protocol. Validators are responsible for verifying transactions. Anyone can become a validator. However, other nodes retain a list of validators they can actually trust. This list is called UNL (Unique Node List). Validators also have a UNL; that is, the validators they trust also want to reach consensus. Currently, Ripple has determined the list of validators that can be trusted, but if the network believes that the validators chosen by Ripple are not trustworthy, they can modify the list in their node software.
You can form a ledger by obtaining the previous ledger and applying all transactions that have occurred since then. Therefore, to reach a consensus on the current ledger, nodes must agree on the previous ledger and the set of transactions that have occurred since then. After creating a new ledger, nodes (including ordinary nodes and validators) start a timer (a few seconds, about 5 seconds) and collect new transactions that have arrived during the creation of the previous ledger. When the timer expires, it selects at least 80% of the transactions that the UNL considers valid and forms the next ledger. Validators broadcast a proposal (a set of transactions they believe to be valid to form the next ledger). Validators can broadcast proposals for the same ledger multiple times if they decide to change the list of valid transactions based on proposals from their UNL and other factors. Therefore, you only need to wait for 5-10 seconds to ensure that your transaction has been confirmed by the network.
Some people wonder if this will lead to many different versions of the ledger, as each node may have a different UNL. As long as there is a minimum level of interconnectivity between UNLs, consensus will be reached quickly. This is mainly because the main goal of each honest node is to reach consensus.
In this chapter, we learned what DApps are and briefly understood their working principles. We saw some of the challenges faced by DApps and the various solutions to these problems. Finally, we gained an overview of some popular DApps and got a general understanding of their features and working principles. Now, you should be able to clearly explain what a DApp is and how it works.
In the previous chapter, we saw what DApps are. We also saw an overview of some popular DApps, one of which is Ethereum. Currently, Ethereum is the most popular DApp after Bitcoin. In this chapter, we will delve deeper into how Ethereum works and what we can develop using Ethereum. We will also see important Ethereum client and node implementations.
In this chapter, we will cover the following topics:
Ethereum User Accounts
What are smart contracts, and how do they work?
Ethereum Virtual Machine
How does mining work in the Proof of Work consensus protocol?
Learn How to Use geth Commands
How to Set Up Ethereum Wallet and Mist
Overview of Whisper and Swarm
The Future of Ethereum
Ethereum is a decentralized platform that allows us to deploy DApps. Smart contracts are written in the Solidity programming language. DApps are created using one or more smart contracts. Smart contracts are programs that run completely according to the program, with no possibility of downtime, censorship, fraud, or third-party interfaces. In Ethereum, smart contracts can be written in several programming languages, including Solidity, LLL, and Serpent. Solidity is the most popular language among them. Ethereum has an internal currency called Ether. Deploying smart contracts or calling their methods requires Ether. Like any other DApp, smart contracts can have multiple instances, each identified by its unique address. User accounts and smart contracts can both hold Ether.
Ethereum uses the blockchain data structure and proof of work consensus protocol. One method of smart contract can be called through transactions or another method. There are two types of nodes in the network: regular nodes and miners. Regular nodes simply have a copy of the blockchain, while miners build the blockchain by mining blocks.
To create an Ethereum account, we only need an asymmetric key pair. There are various algorithms, such as RSA, ECC, etc., used to generate asymmetric encryption keys. Ethereum uses elliptic curve encryption (ECC)online casino entry methodThe latest plan. ECC has various parameters. These parameters are used to adjust speed and security. Ethereum uses parameters. In-depth understanding of ECC and its parameters will require mathematical knowledge, and it is not necessary to deeply understand it for building DApps with Ethereum.
Ethereum uses 256-bit encryptionlottery tutorialThe latest plan. Ethereum private/public key is a 256-bit number. Since the processor cannot represent such a large number, it is encoded as a hexadecimal string of length 64.
Each account is represented by an address. Once we have the key needed to generate the address, here are the steps to generate an address from the public key:
First, generate the hash of the public key. This will give you a 256-bit number.
Discard the first 96 bits, which is 12 bytes. Now you should have 160 bits of binary data, which is 20 bytes.
Now the address is encoded as a hexadecimal string. Therefore, in the end, you will get a byte string of 40 characters, which is your account address.
Now anyone can send Ethereum to this address.
A transaction is a signed data packet used to transfer Ethereum from one account to another or to a contract, to call a contract method, or to deploy a new contract. Transactions are signed using ECDSA (Elliptic Curve Digital Signature Algorithm), which is a digital signature algorithm based on ECC. A transaction includes the recipient of the message, a signature used to identify the sender and prove their intent, the amount of Ethereum to be transferred, the maximum number of computational steps allowed by the transaction execution (referred to as gas limit), and the fee the sender is willing to pay per computational step (referred to as gas price). If the purpose of the transaction is to call a contract method, it also includes input data; or if its purpose is to deploy a contract, it can include initialization code. The product of gas usage and gas price is called transaction fee. To send Ethereum or execute a contract method, you need to broadcast a transaction to the network. The sender needs to sign the transaction with their private key.
If we are confident that a transaction will always appear in the blockchain, then the transaction is confirmed. It is recommended to wait for 15 confirmations before assuming a transaction is confirmed.
Each node in the Ethereum network stores a copy of the blockchain. We need to ensure that nodes cannot tamper with the blockchain, and we also need a mechanism to check if a block is valid. In addition, if we encounter two different valid blockchains, we need a method to determine which one to choose.
Ethereum uses the proof of work consensus protocol to maintain the tamper resistance of the blockchain. The proof of work system involves solving a complex puzzle to create a new block. Solving this puzzle should require a large amount of computing power, making it difficult to create blocks. The process of creating a block in the proof of work system is called mining. Miners are the nodes that mine in the network. Not all DApps that use proof of work implement the same set of algorithms. They may differ in the puzzle that miners need to solve, the difficulty of the puzzle, the time to solve the puzzle, etc. We will learn about the content of Ethereum’s proof of work.
Anyone can become a miner in the network. Each miner independently solves the puzzle; the miner who first solves the puzzle is the winner and will receive five Ethereum and the transaction fees of all the transactions in the block. If you have a more powerful processor than any other node in the network, this does not mean you will always succeed, because the parameters of the puzzle are not exactly the same for all miners. However, if you have a more powerful processor than any other node in the network, it will increase your chance of success. The behavior of proof of work is similar to a lottery system, where processing power can be considered as the number of lottery tickets a person has. Network security is not measured by the total number of miners; instead, it is measured by the total processing power of the network.
There is no limit to the number of blocks a blockchain can have, and there is also no limit to the total number of Ethereum coins that can be produced. Once a miner successfully mines a block, it will broadcast the block to all other nodes in the network. A block has a header and a set of transactions. Each block holds the hash of the previous block, thus creating a connected chain.
Let’s take a look at the difficult problems that miners need to solve, and how to solve them at a high level. To mine a block, first, the new unmined transactions collected by the miner are broadcast to it, and then the invalid transactions are filtered out. A valid transaction must be correctly signed with a private key, the account must have enough balance to make the transaction, etc. Now the miner creates a block, which has a header and content. The content is the list of transactions contained in the block. The header contains information such as the hash of the previous block, block number, random number, target, timestamp, difficulty, miner’s address, etc. The timestamp represents the time when the block was created. Then the random number is a meaningless value, which is adjusted to find the solution to the puzzle. This puzzle is basically to find such a random number that when the block is hashed, the hash is less than or equal to the target. Ethereum uses the ethash hash algorithm. The only way to find the random number is to enumerate all possibilities. The target is a 256-bit number, which is calculated based on various factors. The difficulty value in the header is a different representation of the target, making it easier to handle. The lower the target, the longer it takes to find the random number, and the higher the target, the shorter it takes to find the random number. This is the formula for calculating the difficulty of the puzzle:
Now, any node in the network can check whether the blockchain they own is valid by first checking whether the transactions in the blockchain are valid, verifying the timestamp, then checking whether all the block targets and random numbers are valid, whether the miner has allocated valid rewards to themselves, and so on.
If a node in the network receives two different valid blockchains, then the blockchain with the higher overall difficulty will be considered a valid blockchain.
Now, let’s take an example, if a node in the network changes some transactions in a block, then the node needs to calculate the random number for all subsequent blocks. When it finds the random number for the subsequent blocks again, the network may have already mined more blocks, so this blockchain will be rejected because its overall difficulty will be lower.
The formula for calculating the block target requires the current timestamp, and each block header is attached with the current timestamp. Nothing can prevent miners from using a timestamp other than the current timestamp when mining a new block, but they usually do not do so because the timestamp verification will fail, and other nodes will not accept the block, and it will be a waste of miner resources. When a miner broadcasts a newly mined block, its timestamp is verified by checking whether the timestamp is greater than that of the previous block. If a miner uses a timestamp greater than the current timestamp, the difficulty will be lower because the difficulty is inversely proportional to the current timestamp; therefore, the miner whose block timestamp is the current timestamp will be accepted by the network because its difficulty will be higher. If a miner uses a timestamp greater than that of the previous block and less than the current timestamp, the difficulty will be higher, and therefore, mining the block will require more time; when the block is mined, the network may have already generated more blocks, so this block will be rejected because the difficulty of the malicious miner’s blockchain will be lower than that of the network’s blockchain. For these reasons, miners always use the accurate timestamp, otherwise they will gain nothing.
A random number is a 64-bit unsigned integer. The random number is the solution to the puzzle. Miners continuously increment the random number until they find the solution. Now you must be thinking, if a miner’s hash power exceeds that of any other miner in the network, then can this miner always be the first to find the random number? Well, no.
The hash of the block being mined by the miner is different for each miner, as the hash depends on factors such as the timestamp and miner address, and it is unlikely to be the same for all miners. Therefore, this is not a competition to solve difficult problems, but a lottery system. Of course, a miner may have good luck based on their hash power, but this does not mean that the miner can always find the next block.
The block difficulty formula we saw earlier used a 10-second threshold to ensure that the difference in mining time between the parent block and the child block is between 10-20 seconds. But why is it 10-20 seconds instead of another value? Why is there such a constant time gap limit instead of a constant difficulty?}
Imagine that we have a constant difficulty where miners only need to find a random number (nonce) that makes the block’s hash value less than or equal to the difficulty. Assume the difficulty is very high; in this case, users will not know how long it takes to send Ether to another user. If the network’s computational power is not enough to quickly find a random number that meets the difficulty, it may take a long time. Sometimes, the network may be lucky to find the random number quickly. But this system is difficult to attract users because users always want to know how long a transaction takes to complete, just like when we transfer money from one bank account to another, a time frame should be given for completion. If the constant difficulty is too low, it will harm the security of the blockchain, as large miners can mine blocks faster than small miners, and the largest miner in the network will have the ability to control the DApp. It is impossible to find a constant difficulty value that can stabilize the network because the network’s computational power is not constant.
Now that we know why we should always have an average time for the network to mine a block, the question is, what is the most suitable average time, as it can be any value from 1 second to infinity. Lowering the difficulty can achieve a smaller average time, while increasing the difficulty can achieve a higher average time. But what are the pros and cons of lower and higher average times? Before discussing this issue, we need to first understand what outdated blocks are.
What happens if two miners almost simultaneously mine the next block? Both blocks are definitely valid, but the blockchain cannot accommodate two blocks with the same block number, and neither miner can receive the reward. Although this is a common problem, the solution is simple. Ultimately, the block with higher difficulty will be accepted by the network. Therefore, the block that is finally left as valid is called an outdated block.
The total number of outdated blocks generated in the network is inversely proportional to the average time for generating new blocks. A shorter block generation time means that the newly mined blocks spread throughout the network more quickly, increasing the chances that more than one miner finds a solution to the puzzle. Therefore, when blocks are propagating through the network, other miners may have already solved the puzzle and broadcast it, thus creating outdated blocks. However, if the average block generation time is longer, multiple miners have a smaller chance of solving the puzzle. Even if they do solve it, there may be a time gap between solutions, during which the first solved block can propagate, and other miners can stop mining that block and switch to mining the next one. If outdated blocks frequently appear in the network, it can cause major problems, but if they rarely appear, they will not cause harm.
So, what are the problems with outdated blocks? They delay the confirmation of transactions. When two miners almost simultaneously mine a block, they may not have the same set of transactions, so if our transaction appears in one of the blocks, we cannot say it has been confirmed because the block containing the transaction may be outdated. We need to wait for more blocks to be mined. Due to the existence of outdated blocks, the average confirmation time does not equal the average block generation time.
Can outdated blocks affect blockchain security? Yes, they can. We know that network security is measured by the total computing power of miners in the network. When computing power increases, the difficulty also increases to ensure that blocks will not be generated before the average block time. Therefore, higher difficulty means a more secure blockchain, as it now requires more hash power to tamper with nodes, making it more difficult to tamper with the blockchain; thus, it can be said that the blockchain is more secure. When two blocks are almost simultaneously mined, we will split the network into two parts, each representing a different blockchain, but one will become the final blockchain. Therefore, the network part working on outdated blocks will mine the next block on outdated blocks, which leads to a loss of hash power in the network because the hash power is used for unnecessary things. The two parts of the network may take longer to mine the next block than the average block time because they have lost hash power; therefore, the difficulty will decrease after mining the next block because the time required to mine that block is longer than the average block time. The reduction in difficulty affects the overall blockchain security. If the outdated rate is too high, it will have a significant impact on the security of the blockchain.
Ethereum uses the so-called ghost protocol to address the security issues brought by outdated blocks. Ethereum uses a modified version of the actual ghost protocol. The ghost protocol covers security issues by simply adding outdated blocks to the main blockchain, thereby increasing the total difficulty of the blockchain, as the total difficulty of the blockchain also includes the sum of the difficulties of outdated blocks. But how can outdated blocks be inserted into the main blockchain without causing transaction conflicts? Well, any block can specify 0 or more outdated blocks. Miners are incentivized to include outdated blocks, and they are rewarded for doing so. Moreover, the miners of outdated blocks also receive rewards. Transactions in outdated blocks are not used for confirmation calculation, and the miners of outdated blocks will not receive the transaction fees included in outdated blocks. Please note that Ethereum refers to outdated blocks as uncle blocks.
Here is the formula for calculating how much reward the outdated block miner receives. The remaining rewards go to the nephew block, that is, the block that contains the isolated block:
Since not rewarding outdated block miners does not harm any security, you might wonder why outdated block miners should be rewarded? Well, when outdated blocks occur frequently in the network, it causes another problem, which is solved by rewarding outdated block miners. Miners should receive a reward percentage similar to the percentage of hash power they contribute to the network. When two different miners almost simultaneously mine a block, since the miner is more efficient in mining the next block, it is more likely that the block mined by the miner with more hash power will be added to the final blockchain; therefore, the small miner will lose the reward. If the outdate rate is low, this is not a big problem because the large miner will receive a small increase in rewards; however, if the outdate rate is high, it will cause a big problem, that is, the large miners in the network will eventually receive more rewards than they should. The phantom protocol balances this by rewarding outdated block miners. Since large miners do not get all the rewards but more than they should, we do not reward outdated block miners like nephews; instead, we reward a smaller amount to balance. The aforementioned formula balances this quite well.
The phantom mechanism limits the total number of outdated blocks that can be referenced by nephews, to prevent miners from simply mining outdated blocks and causing the blockchain to stagnate.
No matter how many outdated blocks appear in the network, they will affect the network to some extent. The higher the frequency of outdated blocks, the greater the impact on the network.
A fork occurs when there is a conflict between nodes over the validity of the blockchain, that is, when there are multiple blockchains in the network and each blockchain is validated by some miners. There are three types of forks: regular forks, soft forks, and hard forks.
Regular forks occur due to temporary conflicts when two or more miners almost simultaneously find a block. When one has a higher difficulty than the other, the conflict is resolved.
Changes to the source code may lead to conflicts. Depending on the type of conflict, it may be necessary for miners with more than 50% hash power to upgrade, or for all miners to upgrade to resolve the conflict. When it is necessary for miners with more than 50% hash power to upgrade to resolve the conflict, it is called a soft fork; while when all miners need to upgrade to resolve the conflict, it is called a hard fork. An example of a soft fork is that if the update to the source code makes some old blocks/transactions invalid, this problem can be resolved after more than 50% of the hash power miners have upgraded, because the new blockchain will have a higher difficulty and will eventually be accepted by the entire network. An example of a hard fork is that if the update to the source code is to change the miner’s reward, all miners need to upgrade to resolve the conflict.
Since its launch, Ethereum has undergone various hard forks and soft forks.
The genesis block is the first block in the blockchain. It is assigned to block number 0. It is the only block in the blockchain that does not reference a previous block, because there were no blocks before. It does not contain any transactions because no Ether has been generated yet.
Nodes in two networks will only pair when they both have the same genesis block, that is, only when two nodes have the same genesis block will block synchronization occur, otherwise they will reject each other. Different difficulty genesis blocks cannot replace lower difficulty genesis blocks. Each node generates its own genesis block. For various networks, the genesis block is hard-coded into the client.
Like any other currency, Ether has various denominations. Here are the various denominations:
1 Ether = 1000000000000000000 Wei (Wei)
1 Ether = 1000000000000000 Kwei (Kwei)
1 Ether = 1000000000000 Mwei (Mwei)
1 Ether = 1000000000 Gwei (Gwei)
1 Ether = 1000000 Szabo (Szabo)
1 Ether = 1000 Finney (Finney)
1 Ether = 0.001 Kether (Kether)
1 Ether = 0.000001 Mether (Mether)
1 Ether = 0.000000001 Gether (Gether)
1 Ether = 0.000000000001 Tether (Tether)
EVM (or Ethereum Virtual Machine) is the execution environment for Ethereum smart contract bytecode. Every node in the network runs EVM. All nodes use EVM to execute transactions directed at smart contracts, so each node performs the same computation and stores the same values. Transactions that only transfer Ether also require some computation, that is, to find out if there is a balance at the address and deduct the balance accordingly.
Each node executes transactions and stores the final state for many reasons. For example, if there is a smart contract that stores the names and details of everyone attending a party, a new transaction will be broadcast to the network every time a new person is added. For any node in the network, they only need to read the final state of the contract to display the details of everyone attending the party.
Every transaction in the network requires some computation and storage. Therefore, there needs to be a certain transaction fee, otherwise the entire network will be overwhelmed by spam transactions. Moreover, if there is no transaction cost, miners will have no reason to include transactions in blocks, and they will start mining empty blocks. Each transaction requires a different amount of computation and storage; therefore, each transaction has a different transaction cost.
The EVM has two implementations, namely bytecode virtual machine and JIT-VM. At the time of writing this book, JIT-VM can be used, but its development is not yet complete. In any case, Solidity code will be compiled into bytecode. In the case of JIT-VM, the bytecode will be further compiled. JIT-VM is more efficient than its counterpart.
Gas is a unit of measure for computational steps. Every transaction needs to include a gas limit and the amount it is willing to pay per unit of gas (i.e., the cost per calculation); miners can choose to include the transaction and charge the fee. If the gas used by the transaction is less than or equal to the gas limit, the transaction will be processed. If the total gas exceeds the gas limit, all changes will be reversed, except that the transaction remains valid and the miner can still charge the fee (i.e., the product of the maximum usable gas and the gas price).
Miners decide the gas price (i.e., the price per calculation). If the gas price of a transaction is lower than the gas price decided by the miner, the miner will refuse to mine the transaction. The gas price is an amount in wei. Therefore, if the gas price is lower than the price required by the miner, the miner can refuse to include the transaction in the block.
Each operation in the EVM is assigned a gas consumption amount.
Transaction costs affect the maximum amount of Ether an account can transfer to another account. For example, if an account has a balance of five Ether, it cannot transfer all five Ether to another account because if all Ether is transferred, there will be no balance left in the account from which to deduct the transaction fee.
If a transaction calls a contract method and that method sends some Ether or calls other contract methods, the transaction fee will be deducted from the account that calls the contract method.
To make a node part of the network, it needs to connect to some other nodes in the network so that it can broadcast transactions/blocks and listen for new transactions/blocks. A node does not need to connect to every node in the network; instead, a node connects to some other nodes. And these nodes connect to other nodes. In this way, the entire network is interconnected.
But how do nodes find other nodes in the network? Because there is no central server that everyone can connect to for information exchange. Ethereum has its own node discovery protocol to solve this problem, which is based on the Kadelima protocol. In the node discovery protocol, there is a special type of node called a bootstrap node. Bootstrap nodes maintain a list of all the nodes they are connected to for a period of time. They do not save the blockchain itself. When a node connects to the Ethereum network, it first connects to a bootstrap node, which shares the list of nodes that connected to it during the last predefined time period. The connected nodes then connect and synchronize with the node.
There can be various instances of Ethereum, that is, various networks, each with its own network ID. The two main Ethereum networks are the main network and the test network. The main network is the network where Ether is traded on exchanges, while the test network is used by developers for testing. So far, we have learned everything about the main network blockchain.
Bootnode is the most popular implementation of Ethereum boot nodes. If you want to host your own boot node, you can use bootnode.
Whisper and Swarm are respectively decentralized communication protocols and decentralized storage platforms developed by Ethereum developers. Whisper is a decentralized communication protocol, while Swarm is a decentralized file system.
Whisper allows nodes in the network to communicate with each other. It supports broadcasting, encrypted messages between users, and more. It is not designed to transfer large amounts of data. You can learn more about Whisper and view code examples here.
Swarm is similar to Filecoin, with the main difference being technology and incentive mechanisms. Filecoin does not penalize storage, while Swarm penalizes storage, thereby further increasing the availability of files. You may want to know how the incentive mechanism works in Swarm. Does it have an internal currency? In fact, Swarm does not have an internal currency, but uses the incentive mechanism of Ethereum. There is a smart contract in Ethereum used to track the incentive mechanism. Clearly, the smart contract cannot communicate with Swarm; instead, Swarm communicates with the smart contract. Therefore, you pay for storage through the smart contract, and the payment is released to the storage after the expiration date. You can also report file loss to the smart contract, in which case it can penalize the corresponding storage. You can learn more about the differences between Swarm and IPFS/Filecoin, and view the smart contract code here.
At the time of writing this book, Whisper and Swarm are still under development, so many things are still unclear.
Geth (or known as go-ethereum) is the implementation of Ethereum, Whisper, and Swarm nodes. Geth can be used to become part of all these or only a selected part of them. The reason for merging them is to make them look like a single DApp, so that through a single node, clients can access all three DApps.
Geth is a command-line application. It is written in the Go programming language. It is compatible with all major operating systems. The current version of geth does not support Swarm and only supports some features of Whisper. As of the time this book was written, the latest version of geth is 1.3.5.
Geth is compatible with OS X, Linux, and Windows. It supports two types of installation: binary installation and script installation. As of the time this book was written, the latest stable version is 1.4.13. Let’s see how to install it using the binary installation method on various operating systems. Script installation is used only when you need to modify the geth source code and install it. Since we do not want to make any changes to the source code, we will choose binary installation.
The recommended method to install geth on OS X is to use brew. Run these two commands in the terminal to install geth:
The recommended method to install geth on Ubuntu is to use. Run these commands in the Ubuntu terminal to install geth:
Geth provides executable files for Windows. Download the zip file from and unzip it. Inside, you will find the file.
For more information on installing geth on various operating systems, please visit.
Geth provides a JSON-RPC API for communication with other applications. Geth offers JSON-RPC API using HTTP, WebSocket, and other protocols. The API provided by JSON-RPC is divided into the following categories: admin, debug, eth, miner, net, personal, shh, txpool, and web3. You can find more information about it here.
Geth also provides an interactive JavaScript console for programmatic interaction with its JavaScript API. This interactive console communicates with geth via IPC using JSON-RPC. We will learn more about JSON-RPC and JavaScript API in subsequent chapters.
Let’s learn some important subcommands and options of the geth command through examples. You can use the help subcommand to find a list of all subcommands and options. In the following chapters, we will see more about geth and its commands.
Nodes in the Ethereum network communicate by default using the port. However, nodes can also choose to listen on other port numbers.
To connect to the main network, simply run the command. The following is an example of specifying the network ID and custom directory where geth will store the downloaded blockchain:
Option is used to specify the blockchain storage location. If not provided, the default path is .
Option is used to specify the network ID. 1 is the ID of the main network. If not provided, the default value is 1. The network ID for the test network is 2.
To create a private network, just provide a random network ID. Private networks are usually used for development purposes. Geth also provides various flags related to logging and debugging, which are very useful during development. Therefore, we can simply use the flag to run a private network, enabling various debugging and logging flags without providing a random network ID and various logging and debugging flags.
Geth also allows us to create accounts, i.e., generate the associated keys and addresses. To create an account, please use the following command:
When running this command, you will be prompted to enter a password to encrypt your account. If you forget the password, you will not be able to access your account.
To get a list of all accounts in the local wallet, please use the following command:
The above command will print a list of addresses for all accounts. The keys are stored in the path by default, but you can use the option to specify another directory.
By default, geth will not start mining. To indicate that geth should start mining, simply provide the option. There are also other options related to mining:
Here, in addition to the options, we also provide various other options. The option specifies the total number of threads to use when specifying the hash. By default, eight threads are used. Etherbase is the address where the rewards from mining are deposited. By default, the account is encrypted. Therefore, to access the ether in the account, we need to unlock it, i.e., decrypt the account. Decryption is used to decrypt the private key associated with the account. To start mining, we do not need to unlock it, as we only need the address to deposit the mining rewards. You can use the option to unlock one or more accounts. Multiple addresses can be provided by separating them with commas.
Used to specify the GPU for mining. To get the GPU list, use the command. Each GPU requires 1-2 GB of RAM. By default, it does not use GPU and only uses CPU.
At the time of writing this book, the size of the blockchain is about 30GB. If your internet connection speed is slow, the download may take several hours or even days. Ethereum has implemented a fast sync algorithm that can download the blockchain faster.
Fast sync does not download the entire block; instead, it only downloads block headers, transaction receipts, and the most recent state database. Therefore, we do not need to download and replay all transactions. To check the integrity of the blockchain, the algorithm downloads a complete block after every defined number of blocks. For more information about the fast sync algorithm, please visit.
When using fast sync to download the blockchain, you need to use the flag when running geth.
For security reasons, fast sync will only run during the initial synchronization period (i.e., when the blockchain of the node itself is empty). After the node successfully synchronizes with the network, fast sync will be permanently disabled. As an additional security feature, if fast sync fails near or after a random axis point, it will be disabled as a precautionary measure, and the node will return to a fully block-based synchronization.
The Ethereum wallet is an Ethereum UI client that allows you to create accounts, send Ether, deploy contracts, call contract methods, and so on.
The Ethereum wallet comes with geth. When you run Ethereum, it will try to find the local geth instance and connect to it, and if it cannot find a running geth, it will start its own geth node. The Ethereum wallet communicates with geth using IPC. Geth supports file-based IPC.
If the data directory is changed when running geth, the IPC file path will also change. Therefore, in order for the Ethereum wallet to find and connect to your geth instance, you need to use the option to specify the IPC file location as the default location so that the Ethereum wallet can find it; otherwise, the Ethereum wallet will not be able to find it and will start its own geth instance. To find the default IPC file path, run geth help and it will display the default path next to the option.
Visit to download the Ethereum wallet. It is compatible with Linux, OS X, and Windows. Like geth, it has two installation modes: binary and script installation.
This is an image showing the appearance of the Ethereum wallet:
Mist is the client of Ethereum, Whisper, and Swarm. It allows us to send transactions, send Whisper messages, check the blockchain, and so on.
The relationship between Mist and geth is similar to the relationship between Ethereum wallets and geth.
The most popular feature of Mist is that it comes with a browser. Currently, the front-end JavaScript running in the browser can use the library (a library that provides the Ethereum console JavaScript API for other applications to communicate with geth) to access the web3 API of the geth node.
The basic concept of Mist is to build the third generation of the Internet (Web 3.0), by using Ethereum, Whisper, and Swarm to replace centralized servers, thereby eliminating the need for servers.
This is an image showing the appearance of Mist:
Every system has some weaknesses. Similarly, Ethereum also has some weaknesses. It is obvious that, like any other application, the source code of Ethereum may contain errors. And like any other network-based application, Ethereum is also vulnerable to DoS attacks. But let’s look at the unique and most important weaknesses of Ethereum.
The attacker can try to fill the network, control the ordinary nodes he controls; then you are likely to only connect to the attacker’s node. Once you connect to the attacker’s node, the attacker can refuse to relay all blocks and transactions, thereby disconnecting you from the network. The attacker can only relay the blocks he creates, thereby placing you in another network, and so on.
If the attacker controls more than half of the network computing power, then the attacker can generate blocks faster than the rest of the network. The attacker can simply keep his private branch until it is longer than the branch established by the honest network, and then broadcast it.
With more than 50% of the computing power, miners can cancel transactions, prevent all/some transactions from being mined, and prevent other miners’ mining blocks from being inserted into the blockchain.
Stability is the name of Ethereum’s next major update. As of the writing of this book, stability is still under development. This update will require a hard fork. Stability will change the consensus protocol to Casper and integrate state channels and sharding. The complete details of these works are not yet clear. Let’s look at a high-level overview of what these are.
Before introducing state channels, we need to understand what a payment channel is. A payment channel is a feature that allows us to combine more than two transactions of sending Ether to another account into two transactions. How does it work? Suppose X is the owner of a video streaming website, and Y is a user. X charges one Ether per minute. Now X wants Y to pay after every minute of watching the video. Of course, Y can broadcast a transaction every minute, but there are some problems, such as X has to wait for confirmation, so the video will pause for a while, etc. This is the problem that payment channels solve. With payment channels, Y can lock some Ether (perhaps 100 Ether) for X for a period of time (perhaps 24 hours) by broadcasting a locked transaction. Now after watching 1 minute of video, Y will send a signed record indicating that the lock can be unlocked, and one Ether will be transferred to X’s account, the rest to Y’s account. After another minute, Y will send a signed record indicating that the lock can be unlocked, and two Ethers will be transferred to X’s account, the rest to Y’s account. This process will continue as Y watches videos on X’s website. Now once Y has watched 100 hours of video or 24 hours are about to be reached, X will broadcast the final signed record to the network to withdraw the funds to his account. If X does not withdraw within 24 hours, the full refund will be transferred to Y. Therefore, on the blockchain, we will only see two transactions: lock and unlock.
Payment channels are used for transactions related to sending Ether. Similarly, state channels allow us to combine transactions related to smart contracts.
Before introducing the Casper consensus protocol, we need to understand how the Proof of Stake consensus protocol works.
Proof of Stake is the most common alternative to Proof of Work. Proof of Work wastes too many computing resources. The difference between POW and POS is that in POS, miners do not need to solve puzzles; instead, miners need to prove ownership to mine blocks. In the POS system, the ether in the account is considered as shares, and the probability of a miner mining a block is proportional to the shares held by the miner. So, if a miner holds 10% of the shares in the network, it will mine 10% of the blocks.
But the question is how do we know who will mine the next block? We cannot simply let the miner with the highest share always mine the next block, as this will lead to centralization. There are various algorithms for the selection of the next block, such as randomized block selection and selection based on currency age.
Casper is a modified version of POS that solves various problems of POS.
Currently, each node needs to download all transactions, which is massive. With the rapid growth of the size of the blockchain, it will be very difficult to download the entire blockchain and synchronize it in the coming years.
If you are familiar with distributed database architecture, you must be familiar with sharding. If not, sharding is a method of distributing data across multiple computers. Ethereum will implement sharding to partition and distribute the blockchain among nodes.
You can learn more about the information on sharding the blockchain.
In this chapter, we have gained a detailed understanding of the working principle of Ethereum. We have learned how block time affects security and the weaknesses of Ethereum. We have also learned what Mist and the Ethereum wallet are and how to install them. We have also seen some important commands of geth. Finally, we have learned about the new content in the Ethereum Serenity update.website online casino online website and The most exciting gameplay
In the next chapter, we will learn about various methods of storing and protecting Ethereum.
In the previous chapter, we learned about the working principle of the Ethereum blockchain and how the PoW consensus protocol ensures its security. It is time to start writing smart contracts, as we have a good grasp of the working principle of Ethereum. There are various languages that can be used to write Ethereum smart contracts, but Solidity is the most popular. In this chapter, we will learn about the Solidity programming language. Ultimately, we will build a DApp that can prove the existence, integrity, and ownership of a file at a specific time, a DApp that can prove that a certain file was with a specific owner at a specific time.
In this chapter, we will cover the following topics:
Layout of Solidity source files
Understanding Solidity data types
Special variables and functions of contracts
Control structures
Structure and features of contracts
Compile and deploy contracts
Use the extension to indicate Solidity source files. Like any other programming language, Solidity has various versions. At the time of writing this book, the latest version is 0.4.2.
In the source file, you can use directives to mention the compiler version required to write the code.
For example, let’s look at the following example:
Now, the source file cannot be compiled on a compiler earlier than version 0.4.2, and it also cannot work on compilers starting from version 0.5.0 (the second condition was added using ). Compilers between versions 0.4.2 and 0.5.0 are most likely to contain bug fixes rather than any destructive changes.
More complex rules can be specified for the compiler version; the expression follows the rules used by npm.
Contracts are similar to classes. Contracts contain state variables, functions, function modifiers, events, structures, and enumerations. Contracts also support inheritance. Inheritance is achieved by copying the code at compile time. Smart contracts also support polymorphism.
Let’s look at an example of a smart contract to understand its appearance:
Here is how the aforementioned code works:
Firstly, we declared a contract using a keyword.
Then, we declared two state variables; one stores some data, and the other stores the Ethereum wallet address of the contract deployer, which is also the address of the contract deployment.
Then, we defined an event. Events are used to notify clients of information about something. Whenever there is a change, we will trigger this event. All events are stored on the blockchain.
Then, we defined a function modifier. Modifiers are used to automatically check conditions before executing a function. Here, the modifier checks whether the contract owner has called the function. If not, an exception will be raised.
Then, we had the contract constructor. The constructor is called when deploying the contract. The constructor is used to initialize state variables.
Then, we defined two methods. The first method is to get the value of the state variable, and the second method is to change the value.
Before delving into the characteristics of smart contracts, let’s first learn some other important content related to Solidity. Then we will return to the contract.
All programming languages you have learned before store their variables in memory. In Solidity, variables are stored in memory and in the file system depending on the context.
There is always a default location depending on the context. However, for complex data types such as strings, arrays, and structures, the default location can be overridden by adding or to the type. The default location for function parameters (including return parameters) is memory, the default location for local variables is storage, and of course, the location of state variables is enforced as storage.
Data location is important because it changes the behavior of assignments:
Assignments between storage variables and memory variables always create independent copies. However, assigning from one complex type stored in memory to another complex type stored in memory does not create a copy.
Assignments to state variables (even from other state variables) always create independent copies.
You cannot assign complex types stored in memory to local storage variables.
When assigning state variables to local storage variables, the local storage variable points to the state variable; that is, the local storage variable becomes a pointer.
Solidity is a statically typed language; the data type held by variables needs to be predefined in advance. By default, all bits of variables are assigned a value of 0. In Solidity, variables are function-scoped; that is, any variable declared within a function is effective in the entire function’s scope, regardless of where it is declared.
Now let’s take a look at the various data types provided by Solidity:
The simplest data type is . It can store or .
…… are used to store unsigned integers of 8 bits, 16 bits, 24 bits, … 256 bits, respectively. Similarly, … are used to store 8-bit, 16-bit, … 256-bit signed integers. And are the aliases of and . Similar to and , and are used to represent decimals. … are used to store unsigned decimals of 8 bits, 16 bits, … 256 bits. Similarly, … are used to store 8-bit, 16-bit, … 256-bit signed decimals. If a number requires more than 256 bits of storage space, then use the 256-bit data type, in which case the approximate value of the number will be stored.
Used to store values of up to 20 bytes by allocating hexadecimal literals. It is used to store Ethereum addresses. The type exposes two properties: and . They are used to check the balance of an address, and to transfer Ether to an address. The send method accepts the amount of wei to be transferred and returns true or false based on whether the transfer is successful. Wei is deducted from the contract that calls the method. You can use the prefix in Solidity to assign hexadecimal encoded values to variables.
Solidity supports general arrays and byte arrays. It supports fixed-size and dynamic arrays. It also supports multi-dimensional arrays.
…… are the types of byte arrays. It is the alias of .
Here is an example demonstrating the general syntax of arrays:
Here are some important points about arrays:
Arrays also have a ‘length’ property, which is used to find the length of the array. You can also assign a value to the ‘length’ property to change the size of the array. However, you cannot adjust the size of an array in memory, nor can you adjust the size of a non-dynamic array.
An exception will be thrown if you try to access an unset index of a dynamic array.
Remember that arrays, structures, and mappings cannot be function parameters or function return values.
In Solidity, there are two ways to create strings: using ‘ ‘ and ‘ ‘. ‘ ‘ is used to create raw strings, while ‘ ‘ is used to create UTF-8 strings. The length of a string is always dynamic.
Here is an example demonstrating string syntax:
Solidity also supports structures. Here is an example demonstrating structure syntax:
Please note that function parameters cannot be structures, and functions cannot return structures.
Solidity also supports enumerations. Here is an example demonstrating enumeration syntax:
The mapping data type is a hash table. Mappings can only exist in storage and cannot exist in memory. Therefore, they are only declared as state variables. Mappings can be considered to be composed of key/value pairs. The key is not actually stored; instead, the keccak256 hash of the key is used to find the value. Mappings do not have a length. Mappings cannot be assigned to another mapping.
Here is an example of creating and using a mapping:
Remember that if you try to access an unset key, it will return all 0 bits.
An operator can be applied to any variable, resetting it to its default value. The default value is all bits set to 0.
If we apply an operator to a dynamic array, it will remove all elements, and the length will become 0. If an operator is applied to a static array, all indices will be reset. You can also apply an operator to a specific index, in which case the index will be reset.
Nothing will happen if an operator is applied to a mapping type. However, if an operator is applied to a key of the mapping, the value associated with the key will be deleted.
Here is an example demonstrating the use of operators:
In addition to arrays, strings, structures, enumerations, and mappings, everything else is a basic type.
If an operator is applied to different types, the compiler will try to implicitly convert one of the operands to the type of the other. In general, implicit conversion between value types is possible if it makes semantic sense and no information is lost: it can be converted to, it can be converted to, but it cannot be converted to (because it cannot contain, for example, -1). In addition, unsigned integers can be converted to bytes of the same or larger size, but not vice versa. Any type that can be converted can also be converted to.
Solidity also supports explicit conversions. Therefore, if the compiler does not allow implicit conversion between two data types, you can perform an explicit conversion. It is recommended to avoid explicit conversions as they may bring unexpected results.
Let’s look at an example of an explicit conversion:
Here we explicitly convert the type to, which is to convert a large type to a small type; therefore, the higher-order bits are truncated.
Solidity provides keywords to declare variables. In this case, the type of the variable is dynamically determined based on the first value assigned to it. Once a value is assigned, the type is fixed, so if you assign another type to it, it will cause a type conversion.
Here is an example to demonstrate:
Remember, when defining arrays and mappings, you cannot use . You also cannot use it to define function parameters and state variables.
Solidity supports control structures such as , , , , , and .
Here is an example demonstrating control structures:
Contracts can create a new contract using the keyword. You must know the complete code of the contract being created.
Here is an example to demonstrate:
In some cases, exceptions are automatically thrown. You can manually throw exceptions. The effect of exceptions is that the current execution call is stopped and rolled back (that is, all changes to state and balance are undone). Exceptions cannot be caught:
In Solidity, there are two types of function calls: internal and external function calls. An internal function call refers to a function calling another function within the same contract.
An external function call refers to a function calling a function in another contract. Let’s look at an example:
Calls made using the keyword are called external calls. The keyword in the function represents the current contract instance.
It’s time to delve deeper into contracts. We will look at some new features and delve deeper into the features we have already seen.
The visibility of state variables or functions defines who can see it. Functions and state variables have four visibility levels: , , and .
By default, the visibility of functions is, the visibility of state variables is. Let’s see the meaning of each visibility function:
External functions can only be called from other contracts or through transactions. External functions cannot be called internally; that is, they do not take effect, but they can. You cannot apply visibility to state variables.
Public functions and state variables can be accessed in all possible ways. The accessor functions generated by the compiler are all public state variables. You cannot create your own accessors. In fact, it only generates getters, not setters.
Internal functions and state variables can only be accessed internally, which means they can only be accessed from the current contract and contracts inheriting from it. You cannot use it to access it.
Private functions and state variables are similar to internal functions, but they cannot be accessed by contracts inheriting from them.
Here is a code example to demonstrate visibility and accessors:
We have previously seen what a function modifier is and written a basic function modifier. Now let’s delve deeper into modifiers.
Modifiers are inherited by child contracts, and child contracts can override them. Multiple modifiers can be applied to a function by specifying them in a space-separated list and evaluated in order. You can also pass parameters to modifiers.
In the modifier, the next modifier body or function body, whichever appears first, will be inserted at the place where it appears.
Let’s look at a code example of a complex function modifier:
This is how it is executed:
In this case, it will return when you call the method. But after that, when you try to access state variables, you will get .
Exiting the entire function immediately from within a modifier or function body, and the returned value is assigned to any variable it needs.
For functions, the code after them is executed after the caller’s code is completed. For modifiers, the code after the previous modifier is executed after the caller’s code is completed. In the previous example, lines 5, 6, and 7 will never be executed. Execution starts from line 8 after line 4.
The content inside the modifier cannot be associated with a value. It always returns 0 bits.
A contract can have an unnamed function called a function. This function cannot have any parameters and cannot return anything. If no other function matches the given function identifier, it will be executed when calling the contract.
This function will also be executed when a contract receives Ether without any function calls; that is, when a transaction sends Ether to the contract and does not call any method. In such cases, there is usually very little gas available for function calls (exactly 2,300 gas), so it is important to make the fallback function as cheap as possible.
Contracts that receive Ether but do not define a fallback function will throw an exception and send the Ether back. Therefore, if you want your contract to receive Ether, you must implement a fallback function.
Here is an example of a fallback function:
Solidity supports multiple inheritance through code duplication, including polymorphism. Even if a contract inherits from multiple other contracts, only one contract will be created on the blockchain; the code of the parent contracts is always copied into the final contract.
Here is an example used to demonstrate inheritance:
Keywords are used to refer to the next contract in the inheritance chain. Let’s understand this with an example:
The final inheritance chain of a contract is ,,,, etc. The inheritance chain starts from the most derived contract and ends with the least derived contract.
Contracts that contain only function prototypes and not their implementations are called abstract contracts. Such contracts cannot be compiled (even if they include implemented functions and unimplemented functions). If a contract inherits from an abstract contract and does not implement all the unimplemented functions, it is itself abstract.
These abstract contracts are used to inform the compiler about interfaces. It is useful when you reference a deployed contract and call its functions.
Here is an example to demonstrate this point:
Libraries are similar to contracts, but their purpose is to be deployed only once at a specific address, and their code is reused by various contracts. This means that if a library function is called, its code will be executed in the context of the calling contract; that is, pointing to the calling contract, especially accessing storage from the calling contract. Since libraries are isolated code fragments, they can only access the state variables of the calling contract if they are explicitly provided (otherwise there is no way to name them).
Libraries cannot have state variables; they do not support inheritance and cannot receive Ether. Libraries can contain structures and enumerations.
Once the Solidity library is deployed to the blockchain, anyone can use it, assuming you know its address and have the source code (only a prototype or complete implementation). The Solidity compiler needs the source code to ensure that the method you are trying to access does indeed exist in the library.
Let’s look at an example:
We cannot add the address of the library to the contract source code; instead, the library address needs to be provided to the compiler at compile time.
Libraries have many use cases. The two main use cases of libraries are as follows:
If you have many contracts with some common code, you can deploy that common code as a library. This can save gas because gas depends on the size of the contract. Therefore, we can consider the library as the basic contract used by the contract. Splitting public code using basic contracts instead of libraries will not save gas, because inheritance is implemented by copying code in Solidity. Since libraries are considered basic contracts, functions with internal visibility in the library will be copied to the contract that uses it; otherwise, functions with library internal visibility cannot be called by the contract using the library because external calls are required, and internal visibility functions cannot be called using external calls. In addition, the structures and enumerations in the library will be copied to the contract using the library.
Libraries can be used to add member functions to data types.
If the library only contains internal functions and/or structures/enumerations, the library does not need to be deployed because all the content in the library will be copied to the contract that uses it.
Instructions can be used to attach library functions (from library to any type ) to type . These functions will take the object that calls them as the first parameter.
The effect of using is to attach the functions of the library to all types.
Here is an example to demonstrate this:
Solidity allows functions to return multiple values. Here is an example to demonstrate this:
Solidity allows source files to import other source files. Here is an example to demonstrate this:
There are some special global variables and functions that will be discussed in the following chapters.
The attributes of the block and transactions are as follows:
The hash of the given block is only applicable to the most recent 256 blocks.
The miner’s address of the current block.
: The difficulty of the current block.
: The current block gas limit. It defines the maximum amount of gas that all transactions in the entire block are allowed to consume. The purpose is to keep the propagation and processing time of the block low, thus achieving a sufficiently decentralized network. Miners have the right to set the current block gas limit to 0.0975% (1/1,024) of the previous block gas limit, so the resulting gas limit should be the median of the miner’s preference.
: The current block number.
: The timestamp of the current block.
: The complete calling data includes the function called in the transaction and its parameters.
: The remaining gas.
: The sender of the message (the current call).
: The first four bytes of the calling data (function identifier).
: The amount of wei sent along with the message.
: The timestamp of the current block (alias of ).
: The gas price of the transaction.
: The sender of the transaction (the entire call chain).
The following are the variables related to the address type:
: The balance of the address in wei units
: Send a specified amount of wei to ; return if the operation fails.
The following are the variables related to the contract:
: The current contract, which can be explicitly converted to the type .
: Destroy the current contract and send its funds to the given address.
Literal numbers can be suffixed with _, _, or _ to convert between subunits of ether, without a suffix the number of ether currency is assumed to be wei; for example, is evaluated as .
Let’s write a Solidity contract that can prove ownership of a file without displaying the actual file. It can prove that the file existed at a specific time and ultimately check the integrity of the file.
We will implement ownership proof by storing the hash of the file and the owner’s name. We will implement existence proof of the file by storing the hash of the file and the block timestamp. Finally, the stored hash itself proves the integrity of the file; that is, if the file is modified, its hash value will change, and the contract will not find such a file, thereby proving that the file has been modified.
Below is the code for the smart contract that implements all of this:
Ethereum provides the solc compiler, which offers a command-line interface to compile files. Visit to find installation instructions, and visit to find usage instructions. We will not use the solc compiler directly; instead, we will use solcjs and the Solidity browser. Solcjs allows us to compile Solidity programmatically in Node.js, while the Browser Solidity is an IDE for small contracts, providing an editor and generating the code to deploy contracts.
Now, let’s use the Solidity compiler provided by Ethereum to compile the aforementioned contract. For more information, you can also download the source code of this Solidity browser and use it offline. Visit the download page.
The main advantage of using this browser Solidity is that it provides an editor and also generates the code to deploy the contract.
In the editor, copy and paste the aforementioned contract code. You will see it compiled and given the web3.js code to deploy it using the geth interactive console.
You will get the following output:
Represents the compiled version of the EVM-understandable contract (bytecode). The source code is first converted to opcodes, and then the opcodes are converted to bytecode. Each opcode has gas associated with it.
The first parameter is the ABI definition. ABI definition is used to create transactions because it contains all the method prototypes.
Now run geth in developer mode and enable mining. To do this, run the following command:
Now open another command line window and enter the following command to open the interactive JavaScript console of geth:
This will connect the JS console to another window running the geth instance.
In the right panel of the browser Solidity, copy all the content in the web3 deployment text area and paste it into the interactive console. Now press Enter. You will first get the transaction hash, and after a while, you will get the contract address after the transaction is mined. The transaction hash is the hash of the transaction and is unique for each transaction. Each deployed contract has a unique contract address used to identify the contract in the blockchain.
The contract address is deterministically calculated from the creator’s address (from address) and the number of transactions sent by the creator (transaction nonce). These two parameters are RLP encoded and then hashed using the keccak-256 hashing algorithm. We will learn more about transaction nonce later. You can learn more about RLP at [link].
Now let’s store the details of the file and retrieve them.
Place this code to broadcast a transaction to store the details of the file:
Here, replace the contract address with the contract address you have obtained. The first parameter is the contract address. Here, we do not provide gas, in which case, it will be automatically calculated.
Now let’s find the details of the file. Run this code in order to find the details of the file:
You will get the following output:
The call method is used to call contract methods using the EVM in the current state. It does not broadcast transactions. We do not need to broadcast to read data because we will have our own blockchain copy.
In the following chapters, we will learn more about web3.js.
In this chapter, we have learned the Solidity programming language. We have understood data location, data types, and advanced features of contracts. We have also learned the fastest and simplest method for compiling and deploying smart contracts. Now, you should be able to write smart contracts easily.
In the next chapter, we will build a frontend for smart contracts, which will make deploying smart contracts and running transactions easier.
In the previous chapter, we learned how to write smart contracts and use the interactive console of geth to deploy and broadcast transactions using web3.js. In this chapter, we will learn web3.js and how to import, connect to geth, and use it in Node.js or client-side JavaScript. We will also learn how to use web3.js to build a web client for the smart contract created in the previous chapter.
In this chapter, we will cover the following topics:
Import web3.js in Node.js and client-side JavaScript
Connect to geth
Explore various things that can be done using web3.js
Explore various most commonly used APIs of web3.js
Build a Node.js application for ownership contracts
web3.js provides a JavaScript API for communicating with geth. It internally uses JSON-RPC to communicate with geth. web3.js can also communicate with any other type of Ethereum node that supports JSON-RPC. It exposes all JSON-RPC APIs as JavaScript APIs; that is, it not only supports all APIs related to Ethereum; it also supports APIs related to Whisper and Swarm.
As we build various projects, you will get to know web3.js more and more. But now, let’s first understand some of the most commonly used APIs of web3.js, and then we will use web3.js to build a frontend for our ownership smart contract.
At the time of writing this article, the latest version of web3.js is 0.16.0. We will learn all the contents related to this version.
web3.js is hosted at, and the complete documentation is hosted at .
To use web3.js in Node.js, you just need to run it in the project directory, in the source code, you can use to import.
To use web3.js in client-side JavaScript, you can add the file located in the directory of the project source code to the queue. Now you will be able to use the object globally.
web3.js can communicate with the node using HTTP or IPC. We will use HTTP to establish communication with the node. web3.js allows us to connect to multiple nodes. The instance represents a connection to a node. This instance exposes the API.
When an application runs in Mist, it automatically creates an instance connected to the mist node. The variable name of the instance is .
Here is the basic code to connect to a node:
Firstly, we check here if the code is running in mist by checking if it is. If defined, use the existing instance; otherwise, create an instance by connecting to our custom node. If you want to connect to the custom node regardless of whether the application is running in mist, remove the condition from the previous code. Here, we assume that our custom node is running on the local port number.
The object exposes a constructor (in this context called provider) that is used to establish connections and transmit messages using various protocols. It allows us to establish HTTP connections, while allows us to establish IPC connections.
The property is automatically assigned to the current provider instance. After creating a web3 instance, you can use the method to change its provider. It accepts a parameter, which is the instance of the new provider.
Remember that geth disables HTTP-RPC by default. So when running geth, enable it by passing options. By default, HTTP-RPC runs on port 8545.
It exposes a method to check if connected to a node. It returns or based on the connection status.
It contains an object specifically for interacting with the Ethereum blockchain (in this context called provider), as well as an object for Whisper interactions (). Most of web3.js’s APIs are in these two objects.
All APIs are synchronous by default. If you want to make an asynchronous request, you can pass an optional callback as the last parameter of most functions. All callbacks use error-first callback style.
Some APIs have aliases for asynchronous requests. For example, is synchronous, while is asynchronous.
Here is an example:
It is used to get information about a block by its number or hash. Alternatively, it can accept strings such as (genesis block), (top block of the blockchain), or (block being mined). If no parameters are passed, it defaults to, which is assigned by default.
All APIs that require a block identifier as input can accept one of the following: a number, a hash, or a readable string. If no value is passed, these APIs use the default.
JavaScript is locally very poor at handling large numbers. Therefore, applications that need to handle large numbers and require perfect calculations use libraries to handle large numbers.
web3.js also depends on BigNumber.js. It adds it automatically. web3.js always returns an object as a numeric value. It can accept JavaScript numbers, numeric strings, and instances as input.
Here is an example to demonstrate this:
Here, we use a method to get the balance of the address. This method returns an object. We need to call a method on the object to convert it to a string.
It cannot handle numbers with more than 20 decimal places; therefore, it is recommended to store balances in wei units and convert them to other units when displaying them. web3.js itself always returns and accepts balances in wei units. For example, the method returns the balance of the address in wei units.
web3.js provides APIs to convert wei balances to any other unit and convert balances in any other units to wei.
This method is used to convert wei numbers to any other unit, while this method is used to convert numbers in other units to wei. Here is an example to demonstrate this:
In the first line, we convert wei to Ether, and in the second line, we convert Ether to wei. The second parameter of both methods can be one of the following strings:
Let’s look at the API used to retrieve gas price, address balance, and mined transaction information:
The output format is as follows:
Here is how the aforementioned method works:
: Determines the gas price by the median gas price of the x latest blocks
: Returns the balance of any given address. All hashes should be provided as hexadecimal strings to web3.js’s API, not as hexadecimal text. For Solidity type inputs, they should also be provided as hexadecimal strings.
: Used to obtain detailed information about the transaction using its hash. If the transaction is found in the blockchain, it returns a transaction receipt object; otherwise, it returns null. The transaction receipt object contains the following properties:
: The hash of the block where the transaction is located
: The block number of the block where the transaction is located
: The hash of the transaction
: The integer indicating the position of the transaction in the block
: The address of the sender
: The address of the recipient; if it is a contract creation transaction, then
: The total amount of gas used in the block when this transaction is executed
: The amount of gas used by this specific transaction alone
: If the transaction is a contract creation, it returns the address of the created contract; otherwise, it returns null
: Array of log objects generated by this transaction
Let’s see how to send Ether to any address. To send Ether, you need to use a method. This method can be used to send any type of transaction, but it is mainly used for sending Ether, because deploying a contract or calling a contract method using this method is麻烦, you need to generate transaction data instead of automatically generating it. It accepts a transaction object with the following properties:
This is the address of the sending account. If not specified, it will use the property.
This is optional. It is the target address of the message, which remains undefined in a contract creation transaction.
This is optional. It is the transaction value in wei and (if it is a contract creation transaction) the amount of funds assigned.
This is optional. It is the amount of gas used for the transaction (unused gas will be refunded). If not provided, it will be automatically determined.
This is optional. It is the transaction’s gas price in wei, with the default being the average network gas price.
This is optional. It is a byte string containing message-related data, or the initialization code in the case of a contract creation transaction.
This is optional. It is an integer. Each transaction has a nonce associated with it. The nonce is a counter indicating the number of transactions sent by the sender. If not provided, it will be automatically determined. It helps prevent replay attacks. This nonce is not associated with the nonce of the block. If the nonce we use is greater than the nonce the transaction should have, the transaction will be placed in the queue until other transactions arrive. For example, if the nonce for the next transaction should be 4, and we set the nonce to 10, geth will wait for the six intermediate transactions before broadcasting this transaction. A transaction with nonce 10 is called a queued transaction and is not a pending transaction.
Let’s look at an example of sending Ether to an address:
Here, we send 1 Ether from account number 0 to account number 1. Make sure that both accounts are unlocked with the option when running geth. In the geth interactive console, it will prompt for a password, but if the web3.js API is used outside the interactive console and the account is locked, it will throw an error. This method returns the transaction hash of the transaction. You can then use the method to check if the transaction has been mined.
You can also use the and APIs at runtime to manage accounts.
Let’s learn how to deploy a new contract, obtain a reference to a deployed contract through the address, send Ether to the contract, send a transaction to call the contract method, and estimate the gas used by the method call.
To deploy a new contract or get a reference to a deployed contract, you need to first create a contract object using the method. It takes the contract ABI as a parameter and returns the contract object.
The following is the code to create a contract object:
Once you get the contract, you can use the contract object’s method to deploy it, or use the method to get a reference to the deployed contract that matches the ABI.
Let’s look at an example of deploying a new contract:
Here, the method is called asynchronously, so if the transaction has been successfully created and broadcast, the callback will be triggered twice. The first time is called after the transaction is broadcast, and the second time is called after the transaction is confirmed. If the callback function is not provided, the properties of the variable will be set to. Once the contract is confirmed, the properties will be set.
In the contract, there is no constructor, but if there is a constructor, the constructor’s parameters should be placed at the beginning of the method. The object we pass contains the source address, the bytecode of the contract, and the maximum gas used. These three properties must exist; otherwise, the transaction will not be created. The object can have properties that are the same as the properties passed to the method, but here, it is the bytecode of the contract, and the properties will be ignored.
You can use the method to get a reference to a deployed contract. Here is the code that demonstrates this:
Now let’s see how to send a transaction to call a contract method. The following example demonstrates this:
Here, we call the method of the object with the same name. The object passed to the method has the same properties as the object, but the properties and will be ignored.
If you want to call a method on the node itself rather than create and broadcast a transaction, you can use instead. The following example demonstrates this:
Sometimes, we need to find out how much gas is required to call a method so that we can decide whether to make the call. We can use to achieve this purpose. However, using it directly requires you to generate transaction data; therefore, we can use the method of the object with the same name. The following example demonstrates this:
If you only want to send some Ether to the contract without calling any method, you can simply use the method.
Now let’s see how to listen to the events of the contract. It is very important to listen to events because the results of methods called through transactions are usually returned by triggering events.
Before we delve into how to retrieve and listen to events, we need to learn about the index parameters of events. Up to three parameters of the event can have the property. This property is used to signal the node to index it, so that the client can search for events with matching return values. If the index property is not used, it is necessary to retrieve all events from the node and filter the required events. For example, you can write events as follows:
Here is an example demonstrating how to listen to contract events:
This is how the above code works:
Firstly, we get the event object by calling the method with the same name on the contract instance. This method accepts two objects as parameters to filter events:
The first object is used to filter events by returning values through the index: for example,. By default, all filter values are set to. This means they will match any events of the given type sent from this contract.
The next object can contain three properties: (the earliest block; defaults to), (the latest block; defaults to), and (the list of addresses from which logs are obtained; defaults to contract address).
The object exposes three methods: , and . They are used to get all events within the block range. Similar to, but it monitors changes after getting events. It can be used to stop monitoring changes.
Then, we have the methods of the contract instance. It is used to retrieve all events of the contract.
Each event is represented by an object containing the following properties:
It represents the object containing event parameters.
It represents the string of the event name.
It represents the integer of the index position of the log in the block.
It represents the integer of the index position of the log in the index location created by this transaction.
It represents the string of the hash of the transaction that created this log.
It represents the string of the source address of this log.
It represents the string of the hash of the block where this log is located; it is an empty string when it is in a suspended state.
:represents the block number of the block where this log is located; when it is suspended, it is .
web3.js provides an API to retrieve and listen to events. You can use this API, but the earlier methods for handling events are much simpler. You can learn more information.
In the previous chapter, we wrote the Solidity code for the ownership contract, and in the previous chapter and this chapter, we learned about web3.js and how to call contract methods using web3.js. Now, it’s time to build a client for our smart contract so that users can easily use it.
We will build a client where users can select a file and enter all the owner details, then click submit to broadcast a transaction to call the method of the contract and pass the file hash and owner details. Once the transaction is successfully broadcast, we will display the transaction hash. Users can also select a file and get the owner details from the smart contract. The client will also display the latest transactions in real-time.
On the front-end, we will use sha1.js to get the hash value of the file, use jQuery for DOM operations, and use Bootstrap 4 to create responsive layouts. On the back-end, we will use express.js and web3.js. We will use socket.io so that the back-end can push the latest mined transactions to the front-end at regular intervals without the front-end needing to request data.
web3.js can be used on the front-end. But for this application, this will be a security risk; that is, we are using the account stored in geth and exposing the geth node URL to the front-end, which will put the ether in these accounts at risk.
In the exercise files of this chapter, you will find two directories: and . contains the final source code of the project, while contains empty source code files and libraries to quickly start building the application.
To test the directory, you need to run and replace the hard-coded contract address in with the contract address obtained after deploying the contract. Then, run the application using the command in the directory.
In the directory, you will find a directory and two files named and . contains the back-end dependencies of our application, and is the place where you will put the back-end source code.
The directory contains files related to the front-end. In the directory, you will find which is the Bootstrap library; in the directory, you will find where you place the HTML code of our application; in the directory, you will find the JS files of jQuery, sha1, and socket.io. In you will also find a file where you place the front-end JS code of our application.
Let’s first build the backend of the application. First, run in the directory to install the dependencies required for the backend. Before we start writing backend code, make sure geth is running and rpc is enabled. If you are running geth on a private network, make sure mining is also enabled. Finally, ensure that account 0 exists and is unlocked. You can run geth on a private network with rpc and mining enabled, and also unlock account 0:
Before you start coding, the last thing you need to do is deploy the ownership contract using the code we saw in the previous chapter and copy the contract address.
Now let’s create a single server that will provide HTML to the browser and also accept connections:
Here, we integrate with a server running on a port.
Now let’s create a route to provide static files and the main page of the application. Here is the code to perform this operation:
Here, we use middleware to provide static files. We ask it to look for static files in the directory.
Now let’s connect to the node and get a reference to the deployed contract so that we can send transactions and monitor events. Here is the code to perform this operation:
The code is self-explanatory. Just replace the contract address in the code with the one you get.
Now let’s create a route to broadcast transactions and get information about the file. Here is the code to perform this operation:
Here, the route is used to create and broadcast transactions. Once we get the transaction hash, we send it to the client. We do not take any action to wait for transaction mining. The route calls the contract’s get method on the node itself, rather than creating a transaction. It simply returns any response it receives.
Now let’s monitor the events from the contract and broadcast them to all connected clients. Here is the code to perform this operation:
Here, we check if the status is true, and if so, we broadcast the event to all connected clients.
Let’s start with the HTML of the application. Place this code in the file:
Here is how the code works:
Firstly, we display Bootstrap’s file input field to allow the user to select a file.
Next, we display a text field where the user can input the owner’s details.
Then, we have two buttons. The first button is used to store the file hash and owner’s details in the contract, and the second button is used to retrieve the file information from the contract. Clicking the submit button triggers a method, while clicking the get information button triggers a method.
Then, we have an alert box to display messages.
Finally, we display an ordered list showing the transactions of the contract being mined by the user at the same time on the page.
Now let’s write the implementation code for the method and the method, establish a connection with the server, and listen to messages from the server. Here is the code. Put this code in the file:
This is how the aforementioned code works:
First, we defined the method. In the method, we ensure that the file has been selected and the text field is not empty. Then, we read the file content into a buffer and pass the buffer to the public method of sha1.js to get the hash of the content inside the buffer. Once we have the hash, we use jQuery to send an AJAX request to the route, and then we display the transaction hash in the alert box.
Next, we define the method. First, make sure that the file has been selected. Then, generate a hash like the one generated before and send a request to the endpoint to get information about the file.
Finally, we established a connection using the public method of the library. Then, we waited for the connection event to trigger, indicating that the connection was established. After the connection was established, we listened to messages from the server and displayed detailed information about the transaction to the user.
We do not store files on the Ethereum blockchain because storing files is very expensive and requires a large amount of gas. For our case, we actually do not need to store files because the nodes in the network will be able to see the files; therefore, if users want to keep the file content secret, they will not be able to do so. The purpose of our application is only to prove ownership of the file, not to store and provide files like cloud services.
Now run the node to run the application server. Open your favorite browser and visit. You will see the following output in the browser:
Now select a file, enter the owner’s name, and then click submit. The screen will change to the following content:
Here, you can see that the transaction hash is displayed. Now wait for the transaction to be mined. Once the transaction is mined, you will be able to see this transaction in the real-time transaction list. The screen will look like this:
Now select the same file again, and then click the Get Information button. You will see the following output:
Here, you can see the timestamp and detailed information of the owner. Now we have completed the construction of the client for the first DApp.
In this chapter, we first learned the basic knowledge of using the example web3.js. We learned how to connect to nodes, basic APIs, send various types of transactions, and listen to events. Finally, we built an appropriate production client for our ownership contract. Now, you will be able to comfortably write smart contracts and build UI clients for them to simplify usage.
In the next chapter, we will build a wallet service that allows users to easily create and manage Ethereum wallets, and can also be used offline. We will specifically use the LightWallet library to achieve this goal.