The Ultimate Guide to Python and Blockchain: Part 2
Recapping The First Part
In the first part, we learned the basics of the Python. We learned how if-elif-else and loops work in the system. We have basically learned how to do simple code on Python. In this part, we are going to start creating our blockchain. So, without any further ado, let’s get started!
Creating Our Python Blockchain: Introducing Lists
Alright, so enough with the basics. Now let’s create our blockchain!
We are going to do that by introducing lists. Lists are basically a group of data that could be of any type. They are defined like this:
List_name = [ element 1, element 2, element 3……element n]
The elements, as we have explained before, can be of any data type. It could be an integer, float, string, or even another list (which we are going to use later). Let’s see how this will work. We are going to use our terminal for this:
Some things to note from the code above.
Think of the individual elements of the list as blocks in the blockchain. It is not really that much of a stretch, obviously, we will make this more sophisticated later on. The list itself binds all this data together to give that “chain” element of the blockchain.
Now, another thing you will notice is the index number of each element. The first element has an index of 0. This is why, when we want to print the first element, we say “blockchain”.
Modifying Elements of The List
A list that can’t be modified is useless. You need provisions to add and remove elements from the list. Now, we know that in a Bitcoin-like blockchain it is impossible to remove elements, however, we are still dealing with a list right now.
So, how are we going to do it?
We are going to use two list functions:
The append function adds more elements to the list. So, bring back our old list:
blockchain = [1, 2, 5.6].
If we want to add “Blockgeeks” to it, we will simply say: blockchain.append(“Blockgeeks”)
Now when we print it, it shows:
[1, 2, 5.6, “Blockgeeks”]
Now let’s remove some data.
For that, we are going to use the pop() function, which will remove the last element from the list. So, if we do blockchain.pop, now it will remove “Blockgeeks” and show:
[1, 2, 5.6]
Adding Elements During Runtime via Functions
Now, let’s have some fun.
We are going to use a function to add elements to the list while runtime. Consider this program:
So, we have defined a function called “add_list()” which is going to append 3.2 to the blockchain list every single time it is called. Did you notice how we declared the empty list with: blockchain = ? That was done so that we could show you how you could put in data from scratch.
So, if we print it, this is how it will look. We are back on Visual Studio Code btw.
Giving The List More Blockchain-Like Property
Till now we have pretty much dealt with a normal list. However, there needs to be a more organic connection between the blocks.
The reason why the blocks are connected to one another in a real blockchain is because they include data of the previous block as well. That is exactly what we are going to do by appending the data of the last element to the latest element via a nested list. In python, you can get the data of the last of the list using the [-1] index.
So if the blockchain has [1, 2, 3], then blockchain[-1] gives you 3.
Anyway, let’s check the code, we are going use the input() function to get the value of the element of the blockchain from the user.
So, now when you print this, you will get:
Ok, so far we have given some character to our blockchain, but we still don’t have anything close to our working model. Don’t worry that will get solved soon.
Getting Closer to A Working Blockchain
blockchain = 
“”” Section 1 “””
“”” Section 2 “””
“”” Section 3 “””
“”” Section 4 “””
“”” Section 5 “””
Yeah , we know that that’s a huge block of code however, we have divided the whole thing into different sections to help you understand what is going on in and every part of the code.
What we have attempted to do here is to create a prototype blockchain which does not depend on static declaration. Meaning, Users can themselves fill up the data during run time. This is why, if you see the first line of the code, then you will see that we are starting of with an empty blockchain.
Alright, so let’s start looking into the sections.
Note: We suggest that you copy paste the code above and keep it open in a new window or a doc file. We will keep referring to different part of the code in the explanation below, and it will be simpler for you to keep track.
So, this first section you must be pretty well-versed with by now. We are doing two things here:
- Extracting the last element of the blockchain
- Appending the last element along with the current element in a block to the blockchain.
Take a look at the arguments in add_value function:
The transaction_amount is the value of the transaction that will be put into the blockchain. The last_transaction variable, on the other hand, is the value of the transaction in the last block which is going to be put into the new block.
So, why are we initializing last_transaction to ?
This is done purely to avoid an error during runtime. Think about this, if we are dealing with the first block of the blockchain, then it won’t have any “last_transaction” right? You will need at least two blocks for the concept of “last_transaction” to exist. This is why, in order to remove the possibility of any error in the first block, last_transaction is initialized to .
Let’s call this section the input section. We have two functions here:
In the first function, we are asking the user to enter the value of the transaction amount that they want to enter into the blockchain. Now remember, the input() function returns a string value. So, we use the float() function to change that number into a floating number.
In the second function, we are going to ask the user to input their choice.
Now, you might be wondering, “What choice are you talking about?”
Well, take a Section 5. Specifically the while loop. Do you see the option that we are asking there?
So, the get_user_choice() function is used to take in the choice from the user to help understand what they want to do.
This is a very straightforward section. We are using the for loop to print each block of the blockchain.
Now this is something that we haven’t done so far.
In this section, we are verifying the validity of the blockchain. What exactly do we mean by that.
As you may know, a blockchain should be immutable. Since we are not using any hash functions yet, let’s use something else to show that the chain has been tampered with. This is why, in this function we are using a verify_chain function.
So, what are we doing here?
Firstly, we have two variables:
- Index = A counter which we will use to go through the blocks in the blockchain
- Valid = A Boolean variable which will return True or False as the final value of this function
After that, we are using a for loop to go through the blockchain, quite similar to the previous section where we used a loop to print the blocks. Inside the loop we are using three conditional statements, let’s go through each one of them:
The if Sub-section
This checks if the index is 0 or not. If it is, then the index increments by 1
The elif Sub-section
This is the part where we check if some tampering has been done or not. To understand how this works, imagine this scenario.
So, as you can see, the first element of Block B is the contents of its previous block. So, in this subsection, we are checking if the first element of the Block is equal to the elements of the previous block. If it is then this function True otherwise it returns False.
So, this is a long section, which is why we will need to to differentiate it into different subsections (again).
Subsection 1: Initialization
We start off by initializing the first block of the blockchain. We get the value of the transaction amount (tx_amount) and then enter the value into the block of the blockchain.
Subsection 2: Giving a Choice
Ok so Subsection 1 onwards, all the other subsections are going to be executed within this while loop. So, the first thing that we are doing is giving the users an option to choose what exactly they want to do:
- Add a new transaction
- Print the blockchain
- Manipulate the data
- Quit the process
After that, user_choice stores the user’s data
Subsection 3: if-elif-elif-else
So, depending on the choice, we have 4 possibilities. The code looks like this:
- First, we add the transaction to the blockchain. We fill in the input from the user and store it into tx_amount. Once we have the transaction value, we add that, along with the value of the elements from the last block into the blockchain
- Second, we invoke the print function to print the blockchain
- Third, is the manipulate function. We have incorporated this just to show you how this blockchain will react if the data gets manipulated. So, what happens here is that we change the first element of the blockchain into 2. This only works if the blockchain has more than 1 element (the if condition checks that)
Check the following subsection to know what happens next
- The last part is pretty straightforward. If the user sends some other option, then the else block activates which simply uses “break” to get out of the while loop
Subsection 4: Verification Call
If the user chooses to manipulate the blockchain, then this subsection gets affected. Now remember, the verify_chain() returns a Boolean value:
The verify_chain() returns False if manipulation has been done.
Now, this subsection uses the not keyword, which turns False into True. This in turns activates the print function within the if-block to print “Blockchain manipulated”.
Outputs of The Program
Alright, so now we know how the program works. Let’s check out the outputs.
So, to go through what we have done above
We entered 3 values to our blockchain: 23.5, 43,1, and 5.89
We then printed the blockchain which gives this:
We then tried to manipulate our blockchain by changing a data, but our built-in verification system caught that and gave this output:
Fine, so we have a pretty good structure placed in so far. However, we still need to incorporate . We are going to be using proof-of-work in our blockchain.
If we were to summarize how Proof Of Work Protocol works with the blockchain.
- The miners solve cryptographic puzzles to “mine” a block in order to add to the blockchain.
- This process requires immense amount of energy and computational usage. The puzzles have been designed in a way which makes it hard and taxing on the system.
- When a miner solves the puzzle, they present their block to the network for verification.
- Verifying whether the block belongs to the chain or not is an extremely simple process.
Alright, so let’s look at our code:
“”” Section 1 “””
“”” Section 2 “””
“”” Section 3 “””
“”” Section 4 “””
“”” Section 5 “””
“”” Section 6 “””
“”” Section 7 “””
Ok, so let’s analyze the code.
The first thing that we are doing here is importing hash libraries. We are specifically importing:
- hashlib: To use their hashing functions
- json: We need this package to convert the block from dictionary to string.
After that, we are declaring “reward”, a global variable which is going to store the mining block reward that we are going to give to our miners for mining a block.
Up next we have our genesis block. The genesis block is the first block in the blockchain. We are using 4 metadatas in our block:
- Previous_hash: Stores the hash of the previous block. This will be an empty string as the genesis block will not have any previous hash.
- Index: This is the index of the block in the blockchain. Since genesis block is the first block, its index is initialized to 0. Remember in programming terminology, the first element in a list is in the 0th position
- Transaction: The transaction that is stored inside the blockchain. Since this doesn’t have any, it is an empty list.
- Nonce: We will explain this later. It is initialized to 23 which is a dummy value.
After the genesis block is initialized, it gets added to the blockchain in the next step via blockchain = [genesis_block].
Open_transactions: A list that manages all the outstanding transactions in the blockchain. It is an empty list in the beginning.
Since we are the owner and the sender of this transaction, we have initialized this right in the beginning
Up next we have hashing function hash_block()
Inside it we are returning the hash of the block using this expression:
So, let’s see what we are doing here:
- Using the hashlib’s sha256 hashing algorithm.
- The json.dumps function then comes into play and converts the block which is a dictionary into a json-formatted string. However, the hashlib can’t read that so up next we have….
- The encode() function. This converts the json formatted string to a UTF-8 string which is readable by hashlib.
- The hashlib’s output is a byte hash. So we finally use the hexdigest() method to convert it into a normal string.
In section 2, we have two functions:
- The pow function
So, the valid_proof() function has three arguments:
- Transactions: The transactions inside the block
- Last hash: The hash of the last block
Ok, so what exactly is nonce? Well before that, we need to know what difficulty means. “Difficulty” is the idea of making mining as hard as possible. If mining isn’t hard, then all the coins in the system will be pumped out easily, making them absolutely useless.
So, the way we are calculating the hash of the system is by concatenating the transactions, hash of the last block and the nonce into a single string and then hashing them. The hash is only acceptable if the first two letters of it are zeroes.
That is how we are bringing in difficulty. It is impossible to predict how the hash will turn out to be and it is more of a lucky draw. This is why, it is extremely difficult to get a hash which starts with a specific pattern (such as 2 0s).
The function returns True if the program has a valid hash and False if not.
The pow() function
Up next we have the proof of work or the pow() function.
This function is pretty straightforward:
- First we are the extracting the last block from the blockchain and putting it into last_block
- We are then hashing the last_block and putting them into the last_hash
- The while loops keeps running until the valid_proof function returns TRUE. (The not convert will convert the TRUE into FALSE and hence break out of the loop)
- The nonce is then returned.
In this section we have two functions again:
This one is pretty straightforward. It extracts the last block of the blockchain.
The function takes in the metadata of the transaction, namely:
- Sender name
- Recipient name
- Amount of the transaction
After that, the transaction is appended to the open_transactions list.
In this section we have one function, the mine_block() function which will enable you to mine blocks
So, in this function, the following is going to happen:
- Extract the last block of the blockchain and put it in last_block
- Hash the last block
- Use the pow() function to extract the nonce
- Create a reward_transaction which awards the miner, i.e., us with the reward amount which we have set earlier (10.0 coins)
- The reward_transaction gets appended to the open_transaction list
- Finally, with the new approved nonce, we finally have a new block, which helps us get the metadata of the new block,
- The new block is appended to the blockchain
In this section we have two functions:
This function takes in the metadata of the transaction such as the name of the recipient and the amount of the transaction.
At the same time, take a look at the return statement.
return tx_recipient, tx_amount
This function is returning a tuple (we talked about tuples before remember?)
This function basically takes in the choice of the user and returns it. This is pretty similar to the get_user_choice() function in the previous program.
Similar to the last program, this is the print function which prints the blockchain.
This is also similar to the last program. The user gets a choice to either:
- Enter a transaction
- Mine a block
- Print the blockchain
Let’s now check out the outputs of the program.
Output of the Program
First and foremost, let’s choose option 2 and mine a block. When you do that, we get the following block of hashes:
That seems mind-boggling, until you pay a little closer attention and check the last hash:
Do you see what’s so special about this hash?
Remember the difficulty that we set earlier? We were specifically looking for a hash which started with “00”. This is why, the computer ran through multiple hashes by changing the nonce until it finally stumbled upon a hash which fulfilled the given difficulty criteria.
Alright, so now let’s add a transaction. Suppose I want to send Sam, 2.4 coins, we will choose option 1 and get the following output:
Pay attention to the last line. It shows the two transactions that we have done so far.
Wait…two transactions? We just did one right?
Not quite. Remember that we mined a block before this right? So the block reward transaction is also shown here.
Finally, let’s print the blockchain.
So, we have two blocks:
- Up first, we have the genesis block that we have declared ourselves. The nonce was something that we put in ourselves i.e. 23
- Next, we have the second block, which includes the mining transaction and the transaction that we ourselves did with “Sam”. The nonce of the block is 93
So, there you have it. We at least have somewhat of a working