Use Django to implement a runable blockchain application, django Block

Source: Internet
Author: User
Tags django web server install django pip install django

Use Django to implement a runable blockchain application, django Block

We are new to the rise of digital currencies and want to know the technology behind it-how blockchain is implemented.

 

However, it is not easy to fully understand blockchain. I like to learn in practice and learn more about the technology by writing code. You can build a blockchain to deepen your understanding of the blockchain.

Preparations

This article requires you to have a basic understanding of Python, read and write basic Python, and a basic understanding of HTTP requests.

We know that blockchain is an immutable and ordered chain structure composed of block records. records can be transactions, files, or any data you want, it is important that they are linked through hashes.

Environment preparation

Prepare the environment and ensure that Python3.5, pip, django, requests, urllib, json, and hashlib have been installed.

Installation Method:

pip install django requests

An HTTP client, such as Postman, cURL, or other clients, is also required. This document uses Postman as an example.

Start creating Blockchain

Create a block project using the django-admin startproject block, and create a demo project django-admin startproject demo in the project. The directory structure is as follows:

 

Blockchain

Create a Blockchain class in views and create two lists in the constructor. One is used to store the Blockchain and the other is used to store transactions.

The following is the Blockchain framework:

class Blockchain(object):  def __init__(self):    self.chain = []    self.current_transactions = []  def new_block(self):    # Creates a new Block and adds it to the chain    pass  def new_transaction(self):    # Adds a new transaction to the list of transactions    pass  @staticmethod  def hash(block):    # Hashes a Block    pass  @property  def last_block(self):    # Returns the last Block in the chain    pass

Blockchain is used to manage the chain. It can store transactions and add new blocks. Next we will further improve these methods.

Block Structure

Each block contains attributes: index, Unix timestamp, transactions, workload proof (explained later), and Hash value of the previous block.

The following is the structure of a block:

block = {  'index': 1,  'timestamp': 1506057125.900785,  'transactions': [    {      'sender': "8527147fe1f5426f9dd545de4b27ee00",      'recipient': "a77f5cdfa2934df3954a5c7c7da5df1f",      'amount': 5,    }  ],  'proof': 324984774000,  'previous_hash': "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"}

Here, the concept of blockchain is clear. Each new block contains the Hash of the previous block. This is the key and ensures the immutability of blockchain. If an attacker destroys a previous block, the Hash of all blocks will become incorrect. If you don't understand it, take it easy to understand. Refer to the blockchain accounting principles.

Join transaction

Next we need to add a transaction to improve the new_transaction method.

Class Blockchain (object ):... def new_transaction (self, sender, recipient, amount): "generates new transaction information, which will be added to the next block to be dug: param sender: <str> Address of the Sender: param recipient: <str> Address of the Recipient: param amount: <int> Amount: return: <int> The index of the Block that will hold this transaction "" self. current_transactions.append ({'sender': sender, 'reiient ': recipient, 'amount': amount,}) return self. last_block ['index'] + 1

Method to add a transaction record to the List, and return the index of the block to which the record will be added (the next block to be mined), which will be useful when users submit transactions.

Create new block

When Blockchain is instantiated, we need to construct a creation block (the first block without the previous block) and add a proof of work to it.

Each block must be proven by the workload, which is commonly known as mining. We will continue to explain it later.

In order to construct the creation block, we still need to improveNew_block (), new_transaction (), and hash ()Method:

class Blockchain(object):  def __init__(self):    self.chain = []    self.current_transactions = []    self.new_block(previous_hash=1, proof=100)    self.nodes = set()  def new_block(self,proof,previous_hash= None):    block = {      'index': len(self.chain) + 1,      'timestamp': time(),      'transactions': self.current_transactions,      'proof':proof ,      'previous_hash': previous_hash or self.hash(self.chain[-1]),    }    self.current_transactions = []    self.chain.append(block)    return block  def new_transaction(self,sender,recipient,amount):    self.current_transactions.append({      'sender': sender,      'recipient': recipient,      'amount': amount,    })    return self.last_block['index']+1  @staticmethod  def hash(block):    block_string = json.dumps(block, sort_keys=True).encode()    return hashlib.sha256(block_string).hexdigest()

Through the above Code and comments, you can have a visual understanding of the blockchain. Next, let's look at how the blockchain is dug out.

Understanding workload proof

The new block is constructed based on the workload proof algorithm (PoW. The goal of PoW is to find a number that meets a specific condition, which is hard to calculate but easy to verify. This is the core idea of workload proof.

For ease of understanding, for example:

Assume that the Hash value of the product of an integer x multiplied by another integer y must end with 0, that is, hash (x * y) = ac23dc... 0. Set the variable x = 5, and find the value of y?

Python is implemented as follows:

from hashlib import sha256x = 5y = 0while sha256(str(x*y).encode()).hexdigest()[:4] != "0000":   y += 1   print(y,sha256(str(x*y).encode()).hexdigest()[:4])print(y)

In bitcoin, the workload verification algorithm, known as Hashcash, is similar to the problem above. In order to compete for the right to create a block, the miner is competing for computing results. Generally, the computing difficulty is proportional to the number of characters that the target string must satisfy. After the miner calculates the result, he will receive a bitcoin reward.

Of course, it is very easy to verify this result on the network.

Implementation workload proof

Let's implement a similar PoW algorithm. The rule is: Find a number p so that the Hash value of the string spliced with the proof of the previous block starts with four zeros.

import hashlibimport jsonfrom time import timefrom uuid import uuid4class Blockchain(object):  ...  def last_block(self):    return self.chain[-1]  def proof_of_work(self, last_proof):    proof = 0    while self.valid_proof(last_proof, proof) is False:      proof += 1    return proof  @staticmethod  def valid_proof(last_proof, proof):    guess = str(last_proof*proof).encode()    guess_hash = hashlib.sha256(guess).hexdigest()    return guess_hash[:5] == "00000"

The algorithm complexity can be measured by modifying the number starting with zero. Use four for demonstration. You will find that the time required to calculate the result is greatly increased if one is greater than zero.

Now the Blockchain class is basically complete, and then use HTTP requests for interaction.

Blockchain as API Interface

We will use the Python django framework, a lightweight Web application framework that maps network requests to Python functions. Now let's give it a try:

We will create three interfaces:

/Transactions/new create a transaction and add it to the block/mine to tell the server to mine the new block/chain and return the entire blockchain

Create a node

Our django web server will act as a node in the blockchain network. Let's first add some framework code:

node_identifier = str(uuid4()).replace('-', '')# Instantiate the Blockchainblockchain = Blockchain()def mine(request):  last_block = blockchain.last_block  last_proof = last_block['proof']  proof = blockchain.proof_of_work(last_proof)  print(proof)  blockchain.new_transaction(     sender="0",     recipient=node_identifier,     amount=1,   )   # Forge the new Block by adding it to the chain  block = blockchain.new_block(proof)  response = {     'message': "New Block Forged",     'index': block['index'],     'transactions': block['transactions'],     'proof': block['proof'],     'previous_hash': block['previous_hash'],  }  print(response)  return HttpResponse(json.dumps(response))def new_transaction(request):  values = json.loads(request.body.decode('utf-8'))  required = ['sender', 'recipient', 'amount']  if not all(k in values for k in required):    return 'Missing values'  index = blockchain.new_transaction(values['sender'], values['recipient'], values['amount'])  print(index)  response = {'message': 'Transaction will be added to Block %s'%index}  return HttpResponse(json.dumps(response))def full_chain(request):  response = {    'chain': blockchain.chain,    'length': len(blockchain.chain),  }  return HttpResponse(json.dumps(response))

Add url route node: Run Service

from demo import viewsurlpatterns = [  url(r'^admin/', admin.site.urls),  url(r'^mine', views.mine),  url(r'^transactions/new/', views.new_transaction),  url(r'^chain/', views.full_chain),  url(r'^register', views.register_nodes),  url(r'^resolve', views.consensus),]

Running Service

python manage.py runserver 127.0.0.1:8000

Send transaction

Transaction data sent to the node. The structure is as follows:

{ "sender": "my address", "recipient": "someone else's address", "amount": 5}

Add a transaction to the service

 

Mining

Mining is amazing. It is very simple and has done three things:

Proof of computing workload PoW

Grant a miner (himself) a coin by adding a transaction

Construct a new block and add it to the chain

def proof_of_work(self, last_proof):    proof = 0    while self.valid_proof(last_proof, proof) is False:      proof += 1    return proof  @staticmethod  def valid_proof(last_proof, proof):    guess = str(last_proof*proof).encode()    guess_hash = hashlib.sha256(guess).hexdigest()    return guess_hash[:5] == "00000"

Note that the transaction receiver is our own server node. Most of the work we do is to interact with Blockchain methods. At this point, even if our blockchain is complete, we can actually run it.

Run blockchain

You can use cURL or Postman to interact with APIs.

Let's request http: // 127.0.0.1: 8000/mine for mining.

 

After digging twice, there are three blocks. You can obtain all the block information by requesting http: // localhost: 8000/chain.

{  "chain": [    {      "transactions": [],      "proof": 100,      "timestamp": 1520314374.7261052,      "index": 1,      "previous_hash": 1    },    {      "transactions": [        {          "sender": "0",          "recipient": "27d4aae55b2848dcae52bc722d86e0c3",          "amount": 1        }      ],      "proof": 1771087,      "timestamp": 1520314389.5019505,      "index": 2,      "previous_hash": "32fa73f48240160257e95fdf8422c6df734b5d7e8ceb69a41a5578643c1d36fb"    },    {      "transactions": [        {          "sender": "d4ee26eee15148ee92c6cd394edd9705",          "recipient": "5",          "amount": 500        },        {          "sender": "0",          "recipient": "27d4aae55b2848dcae52bc722d86e0c3",          "amount": 1        }      ],      "proof": 100,      "timestamp": 1520314592.4745598,      "index": 3,      "previous_hash": "e6b1be488e0ed20fe3ec51135e5fafb4dfffaa28a190967106a5dd3e89e4b3aa"    }  ],  "length": 3}

Consistency (consensus)

We already have a basic blockchain that can accept transactions and mining. However, the blockchain system should be distributed. Since it is distributed, what can we do to ensure that all nodes have the same chain? This is the consistency problem. To have multiple nodes on the network, we must implement a consistent algorithm.

Register nodes

Before implementing the consistency algorithm, we need to find a way to let a node know its adjacent nodes. Each node needs to save a record containing other nodes in the network. So let's add several interfaces:

/Register receives a new node list in URL format/resolve executes the consistency algorithm to resolve any conflicts and ensure that the node has the correct link.

Modify the init function of Blockchain and provide a method for registering nodes:

from urllib.parse import urlparse...class Blockchain(object):  def __init__(self):    ...    self.nodes = set()    ...  def register_node(self, address):    parsed_url = urlparse(address)    self.nodes.add(parsed_url.netloc)

We use set to store nodes, which is a simple method to avoid repeated addition of nodes.

Consensus Algorithms

As mentioned above, conflict means that different nodes have different chains. To solve this problem, the longest and most effective chain is the final chain. In other words, the longest valid chain in the network is the actual chain.

We use the following algorithm to reach consensus in the network.

class Blockchain(object):  def __init__(self):    ...  def valid_chain(self, chain):    last_block = chain[0]    current_index = 1    while current_index < len(chain):      block = chain[current_index]      if block['previous_hash'] != self.hash(last_block):        return False      # Check that the Proof of Work is correct      if not self.valid_proof(last_block['proof'], block['proof']):        return False      last_block = block      current_index += 1    return True  def resolve_conflicts(self):    neighbours = self.nodes    new_chain = None    max_length = len(self.chain)    for node in neighbours:      response = requests.get('http://%s/chain' %node)      if response.status_code == 200:        length = json.loads(response)['length']        chain = json.loads(response)['chain']        # Check if the length is longer and the chain is valid        if length > max_length and self.valid_chain(chain):          max_length = length          new_chain = chain    # Replace our chain if we discovered a new, valid chain longer than ours    if new_chain:      self.chain = new_chain      return True    return False

First Method valid_chain() Used to check whether the chain is valid and traverse each block to verify the hash and proof.

2nd Methodsresolve_conflicts() Used to resolve conflicts, traverse all neighboring nodes, and check the validity of the chain using the previous method. If the chain is found to be more effective, replace the chain.

Add two routes to the url, one for registering nodes and the other for resolving conflicts.

from demo import viewsurlpatterns = [  url(r'^register', views.register_nodes),  url(r'^resolve', views.consensus),]

You can run nodes on different machines or enable different network ports on one machine to simulate a multi-node network. Here, you can enable different ports on the same machine for demonstration, run the command on different terminals to start two nodes: http: // 127.0.0.1: 8000 and http: // 127.0.0.1: 8100.

 

Then, dig two blocks on node 8100 to ensure a longer chain, and then access the interface/resolve on node 8000, at this time, the node 8100 chain will be replaced by the node 8000 node chain through the consensus algorithm.

 

Summary

The above section describes how to use Django to implement a runable blockchain application. I hope it will help you. If you have any questions, please leave a message, the editor will reply to you in a timely manner. Thank you very much for your support for the help House website!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.