My blockchain in Python

Mauricio M. Ribeiro
13 min readMar 29, 2019

--

TL;DR;

In this post, I am describing how I did to implement an API in Python, using Blockchain to register bets on the matches of the UEFA Nations League.

In other words, this is a step-by-step guide to implement a blockchain in Python.

The source codes from both the server and the client sides can be found at the Conclusion section. Do not hesitate in forking and improving it if you want to.

Decentralization and Blockchain

Sometimes people do not want their information to be centralized in a place they do not have full control on. In a centralized solution you do not know if important data is accessed by some third party you do not wish to access it. This is one of the reasons there is more and more demand for decentralized applications. With them, you may have full control over all information you share on a network.

Blockchain emerged as a fantastic alternative to put in place a decentralized solution that handles trustworthy transactions between different parties. The most known example of a successful Blockchain implementation is Bitcoin, which handles financial transactions. I invite you to discover more of Blockchain in the link below

The application to be developed here

Let us suppose that a group of people decide to organize a competition of football match betting.

As the World Cup was last year, they choose to make their betting on the semifinals of Europe Nations League. Each player will make their bets on the matches Portugal vs. Switzerland; and Netherlands vs. England.

As they do not know themselves very much, they prefer to go for a Blockchain application to register their bets, and like this there will no be no doubts whatsoever about cheating or somebody changing their results randomly. All bets are treated like a transaction and are properly registered in a chain that is shared among all players. Each person has their own copy of all the bets.

So, let’s start the implementation of this Blockchain!

Installing dependencies

If you don’t have Python installed it, you can download it from here. We will also need pip — package installer for Python — which can be installed following this link.

Then, as a newbie wanting to create my first API in Python, I asked my “friend who knows everything about me and gives this information to I don’t know who” (a.k.a. Google): “create Python API”. It was quite easy to find lots of tutorials teaching how to create APIs in Python. The first results based on a framework, quite easy to use, called Flask. And you can follow the steps to install it from here.

When I first tried to run my example, I had an error saying that pipenv was not installed. Google again, ok easy one, I can install it from here.

Requests is also required to send information between the nodes of our decentralized network. Here it goes.

Last but not least, in order to handle CORS, we need to install this package.

Structure of the blockchain

Each block of our chain will have the following information:

  • the index of the block: an incremental integer
  • a timestamp corresponding to the creation date/time of the block
  • a collection of bets (more details below in this same section)
  • the nonce used to mine the block (more details in the “Mining a block” section)
  • the hash of the block
  • the hash of the previous block
Structure of a block

Each bet in the block contains:

  • the name of the player (the person who is betting)
  • the id of the match
  • the score given by the player to both teams
Structure of a bet

App structure

The structure of our application is very simple. We will only have two files:

  • app.py: this is the main entry point of the application, where the entry points will be defined
  • blockchain.py: this is where we are going to put all the business logic of our blockchain (register bet, mining blocks, proof of work, consensus, etc.)

Initialization of the application

First of all we are going to set up the code to initialize the structure and create the genesis block. The genesis block is the very first block of our Blockchain, and its only purpose here is to have a head for our list with some dummy data.

Initialization code in blockchain.py

The create_new_block function is extremely important to our implementation. This is the function that will create blocks to append to our blockchain, once a node wins the mining challenge (more details in the “Mining” section).

Here, we initialize the Flask framework and we set up CORS to be able to respond to cross-origin requests. We also initialize the blockchain object, passing the current node URL to be set.

From Flask documentation:

__name__ is the name of the current Python module. The app needs to know where it’s located to set up some paths, and __name__ is a convenient way to tell it that.”

The variable app_port will be the port defined by the user when launching the application. Considering that the command to launch the application is

python.py app.py 9000

app_port will have the second parameter defined in the command (in this case, 9000). Then, it sets the current node URL (which use we are going to see in the section “Register nodes in the network”) to http://localhost:<app_port> (in our example, http://localhost:9000)

Get the blockchain

The basic function to test all our functionalities is to get the blockchain.

In the blockchain.py file, we will set the function that will return the whole blockchain in JSON format:

Get Blockchain logic in blockchain.py

In the app.py file, the entry point looks like this:

The @app.route directive indicates that /blockchain will call the get_blockchain function (of course). All that it is going to do is to call the corresponding function of blockchain (b.get_blockchain())

Test it

We can quickly test it via Postman. This is how the request and response will look like:

Calling http://localhost:9000/blockchain to test the get blockchain

Register a bet in the blockchain

So, things are starting to get interesting. We are going to register the bets in our pending_bets array. This array will have all the bets that are going to be registered in the block when mining process achieves. (this means they are not registered in the chain yet).

The register bet logic in blockchain.py

In the app.py file, we need to set up the entry point that will call the register_bet function of blockchain, and register this bet to all nodes registered in our network.

The register and broadcast bet logic in app.py

The /bet/broadcast route is hit when we want to register a bet in our network. This route will hit the function register_and_broadcast_bet, which is going to:

  • call the register_bet function of the blockchain (the one we saw just above)
  • iterate through the array of nodes and, for each one of them, call the /bet route in order to broadcast the bet to all other nodes in the network. The /bet route will fall into the register_bet function

Test it

In order to test it, we can try to register a bet and then call the get blockchain logic to check the registered bet in the pending_bets array.

  • Registering the bet of player “john” on the match “NlEn” (Netherlands vs. England). He bets England is going to win 2–1; so the score of team one (Netherlands) will be set to 1; and the score of team two (England) will be set to 2
Posting to http://localhost:9000/bet/broadcast to test the bet registration
  • Checking the pending bet
The bet is in the pending_bets array

Mining a block

In blockchain, in order to create a block to be registered in the chain, a node needs to pass a proof of work test. It consists of finding a nonce (an integer in our case) that, combined with all the other data in the block, will return a hash code which begins with “0000”.

The first step to accomplish this is to develop the proof of work calculation.

I did some googling and quickly found that with hashlib package I could easily call a SHA256 hash on an object. This is done in the auxiliary function hash_block

The idea in the proof of work is simple: increment the nonce until the hash_block function returns a string starting with “0000”. Once the nonce is found, return it.

Now that we know the details of the proof of work function, let us see the mining logic:

Mining logic in blockchain.py

The mine method will set all the data of the block to be created. Once the proof of work test is validated, the block is created and then, returned.

This is the logic for creating the block. It is the same function called during initialization to create the genesis block, and setting the pending bets into “real” bets in the block:

Create new block function inside blockchain.py

mine is supposed to be a continuous function that will mine and generate blocks during the application’s lifetime. But here we are only registering some few bets made by a reduced number of friends in a group. So let us suppose it is called manually by someone who will just invoke the /mine route in one of the nodes.

Here is the code to be hit by this route:

Mining routing in app.py

The mine function will mine the block and iterate through all nodes in the network, sending the new block to all of them — posting the data to the receive_new_block route of the other nodes — keeping the chain consistent.

Test it

We can test the mining logic by:

  • Registering a bet (like in the previous section)
  • Calling the /mine endpoint
Mining successful
  • Then, we call the get blockchain logic so that we can see that the “pending” bet now is an “official” bet present in a block. Besides this, we can see that the pending_bets array is now empty. You can see also that the hash of the block starts with “0000”:
Block mined with the bet of player “john”

But … how do we do to synchronize all nodes and find a consensus if two or more of them have different versions of the chain?

The answers come in the following section…

Register nodes of the network and the consensus logic

Let us suppose we have two nodes, node_1 running in http://localhost:9000

python app.py 9000

and node_2 running in http://localhost:9001

python app.py 9001

And each one of them has a different chain registered. How to synchronize their chains into only one?

The first part is that we need to register node_2 into the network of node_1. node_2 will have to call the /register-and-broadcast-node endpoint of node_1.

To do this, we do a POST call to

POST http://localhost:9000/register-and-broadcast-node

passing in its body the node to be registered, in JSON format, like this:

{ newnodeurl: "http://localhost:9001" }

In the app.py file we will develop the function to be hit by this endpoint and that will register the new node, and broadcast to all nodes registered in the network:

Register node routing in app.py

And in the blockchain.py file, we append the new node into the array of nodes:

Register node to network logic in blockchain.py

But… what if node_2 had already a chain that is slightly different from the one of the network of node_1? We need to find a consensus so that both nodes — and then all the network — have the same chains, with the same bets.

Here, we are going to use a very simple solution to find a consensus: the network which contains the longest chain keeps it, forcing the other to drop its chain and get the new one.

This is how we are going to develop the /consensus endpoint in app.py:

Here, we iterate through the whole network in order to get the longest chain. If the chain is the same as the one we are holding on, we just keep it. If not, we replace it.

Of course, we can only replace the chain by a new one if this new chain is valid. A chain to be valid needs to :

  1. have all blocks containing the right hash code of the previous block.
  2. have all the blocks containing data consistent with their hash

This is the code in blockchain.py to achieve it:

Logic to check validity of a chain in blockchain.py

Test it

Supposing we have our node_1 running in port 9000 with the block of player “john” created in the previous sections in its chain.

We start node_2 in port 9001 with an empty chain.

  • Get blockchain of node 1
  • Get blockchain of node 2
  • Register node 2 into the network of node 1
  • Consensus logic from node 2 (chain is replaced)
  • Check that blockchain of node 2 is really changed, and network_nodes array contains node 1:
  • Check that blockchain of node 1 remains the same, and network_nodes array contains node 2

Great! Blockchains in both nodes are equal, and network is synchronized.

Check the bets of a player or a match

So, imagine lots of people registered their bets in our application. If we want to know, for example, the bets of one specific player or all bets on a match, we have to look into the blockchain and return the desired bets.

This is the logic in the blockchain.py file:

Get Bets logic in blockchain.py

The function get_bets looks for bets in the blockchain following a specific filter contained in the filter variable.

The variables are filled by the app.py method which responds to the /player/<player_name> route (when looking for bets of a player) or to the /match/<match_id> (when looking for bets done on a match).

Get bets for player or match routing in app.py

Test it

After registering the bet of player John, and mining the block (remember: we are looking for official, and not pending, bets), we can call http://localhost:9000/player/john to retrieve the bet that John did for the match Netherlands vs. England:

Also, we can call http://localhost:9000/match/NlEn to retrieve all bets done for the match Netherlands vs. England:

Client test application

Besides the steps that I described in the previous sections, another way for you to test this application is by using a very simple client app that registers and sends bets to the Blockchain.

It is downloadable from here. To run it, open a terminal, browse to the path of the downloaded solution, and run the following instruction.

$ npm i && npm start

This will automatically open the test page. Once the page is open, type the name of the player and the scores of the two matches and hit the “Send Bets” button.

Once the bets are sent, you can use Postman to check that the bet is well registered in the pending_bets array.

Then, we call the mine function

And finally, we can see that the block with the two bets of player Mary are registered (check the block of index 3 below).

In the client app, just call http://localhost:3000/player/mary:

Conclusion

In order to succeed in the programming/web development world we need to work on benchmark and self-learning abilities. The techs we learn to use when we start coding may not be the same in a couple of years.

Blockchain is a concept that is gaining big importance, with the demand of decentralized and trustworthy solutions. And Python is a language that has a strong appeal today.

If you want to improve my solution (remember, I’m a newbie in these topics :) ) or just to check the whole code, do not hesitate in forking my API solution:

Note: In a next version of the app, we can add to each bet the amount of any crypto currency the player wants to bet.

I am also willing to improve my React knowledge. This is why I developed the client solution using this framework. If you have a strong knowledge — or know someone who does — do not hesitate in taking a look and — why not — improve the solution:

--

--