Python is a simple, easy-to-learn, elegant, and powerful programming language. It has a free and open community environment that provides development frameworks and libraries for areas such as web development, web scraping, data analysis, and machine learning, which can be used directly for rapid development. Additionally, Python code is often referred to as executable pseudocode; good Python code is clean, concise, and easy to understand, which is why Python is chosen as the development language to implement a blockchain prototype.
Python is a widely used high-level programming language invented by Dutchman Guido van Rossum, with the first version released in 1991. Python was named after the BBC television series "Monty Python" because van Rossum is a fan of the show. Van Rossum's vision for Python is "beautiful," "explicit," and "simple."
Thus, Python's syntax is straightforward and easy to understand, making it accessible even for programming beginners. Python also comes with rich data structures and libraries, allowing even novices to easily implement very complex programs.
The philosophy of Python developers is: there should be one—and preferably only one—obvious way to do it. This philosophy is deeply reflected in the design of Python programs. When developing Python programs, if faced with multiple choices, Python developers generally reject fancy syntax in favor of clear and unambiguous syntax. These guidelines for Python programming are known as "The Zen of Python." Tim Peters, a Python developer, summarizes "The Zen of Python" as follows:
● Beautiful is better than ugly.
● Explicit is better than implicit.
● Simple is better than complex.
● Complex is better than complicated.
● Flat is better than nested.
● Sparse is better than dense.
● Readability counts.
● Special cases aren’t special enough to break the rules.
● Although practicality beats purity.
● Errors should never pass silently.
● Unless explicitly silenced.
● In the face of ambiguity, refuse the temptation to guess.
● There should be one—and preferably only one—obvious way to do it.
● Although that way may not be obvious at first unless you’re Dutch.
● Now is better than never.
● Although never is often better than right now.
● If the implementation is hard to explain, it’s a bad idea.
● If the implementation is easy to explain, it may be a good idea.
● NameSpaces are one honking great idea—let’s do more of those!
These principles lead Python developers to focus on simplicity, avoid complexity, and pay more attention to how to solve problems efficiently, which is worth considering and following for every developer.
Now let's enter the world of Python, and the first step is to set up a Python development environment.
- Python Installation
The installation process for Python is relatively simple. Go to the official Python website: https://www.python.org/downloads/ to download the Python installation file for your operating system. The download page for the Python installation file is as shown.
- Choose a Python Code Editor
First, choose a suitable Python code editor.
To do a good job, one must first sharpen their tools. Although you can use the built-in text editor of your operating system, such as Notepad, to write Python code, such editors lack features like code highlighting, auto-completion, and error prompts, which greatly reduce development efficiency. Therefore, it is necessary to choose a comprehensive Python code editor to effectively improve development efficiency and code quality. Here is a simple comparison of several mainstream Python code editors, including PyCharm, Sublime Text 3, Visual Studio Code, Atom, and Jupyter Notebook, allowing readers to choose one that suits their needs.
● PyCharm is a full-featured integrated development environment specifically for Python. It can be quickly installed and used on Windows, Mac OS X, and Linux systems. PyCharm integrates various functions related to Python development, such as editing, debugging, and code management, allowing you to start writing code as soon as you open a new file. PyCharm starts a bit slowly but is suitable for developing and managing large projects.
The download link for Atom is https://atom.io/.
● Jupyter Notebook is a web-based Python editor that allows you to write and execute code in a browser, with execution results displayed in rich media formats like HTML. Additionally, Jupyter Notebook supports writing mathematical formulas using LaTeX and documents using Markdown.
Jupyter Notebook does not require additional installation files; it can be installed using the Python package management tool in the terminal (Linux and Mac OS) or command line window (Windows) with the following command:
pip install jupyter
This book will use Jupyter Notebook for Python code development and debugging.
After introducing the editor, let's briefly understand Python's package management tool.
(2) Install Python Package Management Tool
The most popular Python package management tool is the pip command, which will be installed along with the Python installation file.
Other commands can be viewed using pip help, as shown in the figure.
After introducing the package management tool, let's learn about Python's virtual environment.
(3) Create a Python Virtual Environment
During Python development, it is necessary to install third-party packages and dependencies, which often differ for different projects. To prevent conflicts between packages and dependencies across different applications, it is best to create an independent Python development environment, known as a Python virtual environment. This allows each project's environment to be isolated from others, ensuring that the development environment is not affected by other projects and resolving package conflicts. The method to create an independent environment is to use a virtual environment management tool.
The most popular Python virtual environment management tool is called virtualenv, which is a third-party tool for Python. The installation command is as follows:
pip install virtualenv
Once installed, you can create an independent Python virtual development environment. Name this virtual environment venv, and the creation command is virtualenv venv -p python3, where "-p python3" specifies the Python version as Python 3.
To use this virtual environment, you need to activate it first with the command source venv/bin/activate. Once activated, the name of the current virtual environment will be displayed at the beginning of the current line.
At this point, the current Python development environment is the previously created venv virtual environment. To exit the current virtual environment, you can use the deactivate command, and after exiting, the name of the virtual environment (venv) will also disappear.
- Starting and Using Jupyter Notebook
Next, install Jupyter in the Python virtual development environment and start Jupyter Notebook. The commands and execution process for installing and starting Jupyter Notebook are shown in figures 4-12 and 4-13, with the start command being jupyter notebook.
After starting Jupyter Notebook, a page will automatically open in the browser (the program listens on port 8888 by default), as shown in figure 4-14.
This page displays the contents under the "Files" tab, listing the file directory structure of the current folder. The second tab "Running" shows the currently running notebook pages, and the third tab "Clusters" displays the clustering function. To write Python code, you can select the "New" menu in the upper right corner and choose "Python 3" from the dropdown to create a new notebook page, as shown in figure 4-15.
The newly created notebook page can be divided into four areas: title, menu bar, toolbar, and editing area, as shown in figure 4-16.
Figure 4-16 Jupyter Notebook editing page
The title defaults to "Untitled," which can be modified by double-clicking the title area. The menu bar includes all operations for the notebook, and the toolbar displays commonly used commands.
Now let's start writing the first Python program.
- The First Python Program
The function of the first Python program is quite simple: it outputs the phrase "Hello, Blockchain," implemented using Python's print function. After entering the code print("Hello, Blockchain"), click the "Run" button on the toolbar or use the shortcut key <Shift+Enter> to execute the code, as shown in figure 4-17. You can see the result "Hello, Blockchain" printed below.
A block consists of two parts: the block header and the block body. The block header includes the version, parent block hash, data, Merkle root, timestamp, target difficulty, and nonce value; the block body can actually contain any content. In Bitcoin, it includes the number of transaction inputs, the number of transaction outputs, and a variable-length transaction record. In Ethereum, the block body contains not only transaction data but also smart contracts. For ease of development and understanding, the blockchain system to be developed here simplifies the structure of the block, using only the most critical fields and ignoring other non-essential fields. The simplified block includes four fields: parent block hash, data, timestamp, and hash value. The block's hash value is calculated by concatenating the parent block hash, data, and timestamp fields and applying a hash algorithm. The structure of the block is defined using Python, as shown in the figure.
(2) Define the Structure of the Blockchain
A blockchain is a chain made up of blocks. After defining the structure of a block, it is also necessary to define the structure of the blockchain. Each block is linked sequentially by hash values, and all these blocks are placed in an array. Initially, the list is empty, and new blocks are added to this list one by one. A function is then defined to implement the functionality of adding blocks to this list, thus defining the structure of the blockchain.
Blockchain Structure
This completes the simplest blockchain structure. Next, we will gradually improve it to achieve a real blockchain system.
(3) Implement the Blockchain Prototype
- First, create the first block, also known as the genesis block. The code is shown in figure 4-34. The genesis block has no parent block, so the value of prev_hash is empty.
- Next, create two blocks with data regarding Zhang San's transfer record. The prev_hash values are the hash values of the previous blocks, as shown in the figure.
- Then create a blockchain and add the above blocks to it, as shown in figure 4-36.
- Finally, print the current information of the blockchain. You can see that this blockchain contains three blocks, as shown in the figure.
This implements the simplest blockchain prototype, but it lacks core blockchain functionalities, such as consensus mechanisms, accounts and transactions, and decentralized networks, so it cannot be considered a true blockchain. Next, we will gradually add various features of the blockchain to this prototype until a complete blockchain is achieved. First, we will add a consensus mechanism—PoW (Proof of Work).
The consensus mechanism is an important part of blockchain technology. Several common consensus mechanisms have been introduced in section 3.1. Here, we will implement a relatively simple PoW, which is the Proof of Work mechanism. The principle of PoW is to continuously compute until a random number (Nonce) is found that makes the generated hash value meet certain conditions, as shown in the figure.
Next, we will add the Proof of Work mechanism to the above blockchain prototype.
- First, update the structure of the block to include the Nonce field, as shown in the figure.
- Hash Algorithm Library
Python has a built-in hash library—hashlib, which provides common hash algorithms such as MD5 and SHA256. Below are the usage methods for MD5 and SHA256, as shown in the figure.
Base64 is a method of representing arbitrary binary data using 64 characters. Python has a built-in Base64 library for use. The following content shows the process of encrypting and decrypting the string "Hello, Blockchain" using Base64, with the code shown in the figure.
In Python, when using asymmetric encryption algorithms, such as elliptic curve algorithms, it is necessary to install third-party libraries. Here is a brief explanation of how to use the elliptic curve algorithm in Python. To use the elliptic curve algorithm, you need to install the third-party library ECDSA. The installation command is as follows:
pip install ecdsa
After installation, first import the algorithm library, generate a pair of private and public keys, then sign with the private key and verify the signature with the public key, as shown in figure 4-29. First, use the SigningKey.generate() method to generate a private key, from which a unique public key can be derived. Then, use the private key to generate a signature for the string "Something," and the public key generated from the private key can be used to verify whether this signature is correct.
Finally, we introduce Python's plotting library Matplotlib, which is used to generate common charts and perform data visualization. Matplotlib supports various platforms and is powerful enough to easily draw various professional graphs. To use this library, you need to install it first. The installation command is as follows:
pip install matplotlib
The usage of the Matplotlib library is shown in the figure.
Having detailed the structure of a block, which includes the block header and block body, the block header consists of the version, parent block hash, data, Merkle root, timestamp, target difficulty, and nonce value; the block body can actually contain any content. In Bitcoin, it includes the number of transaction inputs, the number of transaction outputs, and a variable-length transaction record. In Ethereum, the block body contains not only transaction data but also smart contracts. For ease of development and understanding, the blockchain system to be developed here simplifies the structure of the block, using only the most critical fields and ignoring other non-essential fields. The simplified block includes four fields: parent block hash, data, timestamp, and hash value. The block's hash value is calculated by concatenating the parent block hash, data, and timestamp fields and applying a hash algorithm. The structure of the block is defined using Python, as shown in the figure.
A blockchain is a chain made up of blocks. After defining the structure of a block, it is also necessary to define the structure of the blockchain. Each block is linked sequentially by hash values, and all these blocks are placed in an array. Initially, the list is empty, and new blocks are added to this list one by one. A function is then defined to implement the functionality of adding blocks to this list, thus defining the structure of the blockchain, as shown in the figure.
This completes the simplest blockchain structure. Next, we will gradually improve it to achieve a real blockchain system.
(3) Implement the Blockchain Prototype
- First, create the first block, also known as the genesis block. The code is shown in figure 4-34. The genesis block has no parent block, so the value of prev_hash is empty.
- Next, create two blocks with data regarding Zhang San's transfer record. The prev_hash values are the hash values of the previous blocks, as shown in the figure.
- Then create a blockchain and add the above blocks to it, as shown in the figure.
- Finally, print the current information of the blockchain. You can see that this blockchain contains three blocks, as shown in the figure.
Several important consensus mechanisms have been mentioned. In the process of calculating Proof of Work, the computation for "mining" is very large, while the verification method is simple and requires little computation. From the code in the figure, it can also be seen that the time consumed for "mining" is 1.42s, while the verification time only takes 0.026s (26μs). It is clear that verification is much simpler than computing Proof of Work.
- After completing the Proof of Work mechanism, generate a new blockchain that incorporates the Proof of Work mechanism, as shown in the figure.
Printing the block information of the above blockchain shows that the hash values of the blocks all start with "00000," as shown in the figure.
It has been mentioned that in blockchain technology, an account is essentially an address in the blockchain network used to identify a node in the network. A wallet is a tool used to store accounts. The essence of an account is a unique pair of private and public keys, meaning that the essence of a wallet is a tool for generating and managing these key pairs. The following are the steps to create a wallet, account, and implement its transaction functionality.
(1) Create Wallet and Account
First, define a Wallet class to represent the wallet. When the Wallet is initialized, it will generate a unique pair of private and public keys, i.e., an account. The generation algorithm is based on the elliptic curve algorithm, as shown in the figure.
- Generate Signature
After creating an account, it is also necessary to provide the address and public key of this account and generate a signature using the account's private key. The address is derived from the public key first through a hash algorithm and then through Base64 algorithm calculation. The signature generated is a string of binary data, which is converted into an ASCII string for easier viewing, as shown in the figure.
Account address, public key, and signature
(3) Generate Verification Function
Next, a verification function needs to be implemented to verify whether the signature is correct. The code for generating the verification function is shown in the figure.
(4) Test Wallet Functionality
Next, test the wallet functionality, including: account generation, account address, public key information, and whether the signature functionality works correctly, as shown in figure 4-48.
Based on the above public key and signature, the correctness of the signature can be verified. The return result of the code execution is True, indicating that this signature was generated based on the private key paired with this public key, meaning that the wallet (account) functionality is normal.
After implementing the functionality of wallets and accounts, we also need to add transaction functionality. To support transactions, we need to define a data structure for transactions.
In the previous steps, the data in the block structure was just a simple string, while in an actual blockchain, the data consists of transaction records. These transaction records need to include the sender, receiver, transaction amount, and the sender's public key and signature for transaction verification. Here, we define a Python class Transaction that includes these fields, as shown in the figure.
(6) Integrate Wallet and Transaction Functionality
After completing the wallet and transaction functionalities, we will update these two functionalities into the previously completed blockchain prototype.
- First, replace the data in the block structure with a transaction list, as shown in the figure.
- Next, add a reward mechanism to the Proof of Work. This reward mechanism allows for receiving cryptocurrency as a reward for successfully mining a block. Here, we assume that 1 cryptocurrency is awarded for each completed block, as shown in the figure.
- Then, to facilitate obtaining the cryptocurrency balance of accounts in the blockchain, we will add a query function named get_balance. This function will traverse all transaction data in the blockchain, match the account, and sum up all incoming amounts while subtracting all outgoing amounts to calculate the current balance of the account, as shown in the figure.
- Test Blockchain Transaction Functionality
Finally, let's test whether the blockchain transaction functionality can operate normally. First, initialize an empty blockchain and three wallet accounts (alice, tom, bob), as shown in the figure. You can see that the initialized wallet balances are all 0.
Next, suppose alice generates the genesis block and adds it to the blockchain. According to the Proof of Work mechanism, alice will receive 1 cryptocurrency, as shown in the code.
After receiving the reward, alice can transfer 0.3 cryptocurrency to tom, as shown in the code.
Assuming this transfer transaction is broadcast to the blockchain network and verified by bob, who generates a new block and adds it to the network, bob will also receive 1 cryptocurrency, as shown in the code.
Print the wallet balances at this point. You can see that after alice transferred 0.3 cryptocurrency to tom, her balance became 0.7, tom now has 0.3 cryptocurrency, and bob received 1 cryptocurrency for mining, as shown in the figure.
At this point, this blockchain system can support mining rewards and transaction functionalities! However, the actual blockchain operates in a decentralized network. In the next section, we will implement a simple decentralized blockchain network.