Read this and still not get blockchain? Building a blockchain from scratch in Python

Read this and still not get blockchain? Building a blockchain from scratch in Python

Source | 51CTO Tech Stack, compiled from the internet. If you have not heard of the 3 o’clock blockchain group, you are not part of the blockchain circle; if you have not joined the 3 o’clock blockchain group, you are not a blockchain big shot; if your feed has not been flooded by the 3 o’clock blockchain group, you do not yet understand what ‘one day in crypto, one year in the mortal world’ feels like.

‘Three o’clock blockchain’ has undoubtedly become the root of everyone’s anxiety during the Spring Festival, and ‘blockchain’ is destined to be an industry hot topic that keeps being discussed and watched through 2018. On March 1, Zhu Xiaohu fired another shot at the surging blockchain craze: in a WeChat Moments post with a picture covered in blockchain applications, Zhu questioned: all these applications added together, how many daily active users do they have? ‘The 2000 internet bubble at least still had eyeballs — what does today’s blockchain have besides coin speculation?’ Before that, Zhu Xiaohu shared on Moments a satirical article about the blockchain investment craze, ‘Come, drink this bowl of blockchain poison chicken soup!’, and declared: ‘Do not drag me into any 3 o’clock group. Some trends I would rather miss, some money I would rather not make — everyone, take care of your late-life reputation.’ Zhu Xiaohu also said that calling ICO a Ponzi scheme is an insult to Ponzi schemes. As a programmer, if you still do not understand this technology, you might be eliminated in 2018! Now let us start with ten humorous jokes to get into blockchain! LOL! Ten blockchain jokes 1. If you were a woman, and every time your boyfriend said something sappy to you or promised to buy you something, you immediately recorded it and sent it to all your and his besties, classmates, colleagues, plus every group chat and Moments feed, so he could never deny it again — that is blockchain. 2. Mahjong is China’s traditional blockchain project: four miners to a group, and the miner who first hashes out 13 numbers with a correct hash value wins the right to record and gets a reward. Immutable. Because convincing the other three people would burn too much hashrate and stamina. 3. Girls who play at nightclubs and guys who play with virtual coins share a few similarities:

  • They are all self-proclaimed smart, elite groups
  • Anyone who does not make them money is an idiot loser
  • They all know lots of big shots
  • They all understand lots of principles
  • They are all waiting for their own price — or their own coin’s price — to rise so someone else takes the bag
  1. Blockchain is a serious technology; whether the various coins are serious, nobody knows. 5. Wu Sangui’s furious rage at Shanhaiguan was essentially a fight for the right to sleep with Chen Yuanyuan; the big shots sniping at each other on the blockchain road are essentially fighting for the right to harvest leeks. 6. Just as the new semester began, the son asked his dad: ‘How should I fill in the father’s occupation column? Should I write coin holder?’ The dad hesitated, then said: ‘Just write shareholder of multiple listed companies.’ 7. Digital currency has been hot lately, and many altcoins have grown several-fold or dozens-fold. Many coin speculators have started to float on air, shouting about ‘one coin, one hot model’. A friend asked me whether to follow along. My view is simple: a gold rush, everyone piling in, is very risky. So let them shout ‘one coin, one hot model’ — do not follow the trend and blindly speculate. We should make money off them: go be the hot model! Be the hot model! Hot model! 8. Yesterday I ran into a fellow coin investor and asked him: ‘With the coin market crashing lately, how is your sleep?’ He said: ‘Not bad, I sleep like a baby!’ I said: ‘I envy you.’ He said: ‘It means sleeping one hour, waking up, then crying for an hour, then sleeping another hour, getting up and crying for another hour.’ 9. An older comrade said earnestly to the post-80s and post-90s generation: ‘Stop playing with those bitcoins and virtual things. Do something real — buy a house in Beijing, get a wife, how nice!’ The post-90s replied: ‘You people pushed houses that cost a few thousand yuan up to 100,000 per square meter. If we do not find another way out and sell you strings of numbers at 100,000 each, how could we ever afford a house?’ 10. First, thanks to the company for putting up bitcoin worth 1 million yuan as an employee reward; second, I feel very lucky to get that 950,000 reward; then I think I still need to plan carefully what to do with this 860,000, since 700,000 is no small sum either. I plan to give 200,000 to my parents, and I have not figured out what to do with the remaining 360,000 yet. In short, thanks to the company for the reward of bitcoin worth 300,000, thank you, and I wish everyone could get this 150,000 reward like I did. Illustrated: understand what blockchain really is in plain language

what is blockchain

‘Blockchain is merely a technology’, and ‘bitcoin’ is merely one application of blockchain technology — just as a person may know the craft of cooking, but applying that craft can produce all kinds of dishes such as ‘kung pao chicken’ or ‘fish-flavored shredded pork’. So what exactly is ‘blockchain’? Here we borrow a fairly popular joke from the internet and present it in graphical form. We can abstract ‘bitcoin’ into ‘someone’s photos’ as shown above. If many users online want to get someone’s photos, they need to search on a fixed website. Of course, there is nowhere else you can go, so fine — that website pops up ads and little windows at you every day and you just have to put up with it, because this is the only place to get them. What is more, what if the site suddenly gets shut down by the police? Or loses power? Loses network? Whatever it is, the server crashes — then the tragic fans of ‘so-and-so’ lose the place that provided all 2,100 of those beloved photos. This is the new online word ‘centralization’. Its drawback is that resources are concentrated in one place, so fault tolerance and risk resistance are weak. Resources are easily lost. So how do we solve this? Let us imagine: could every fan of ‘so-and-so’ hold all 2,100 photos themselves? Like the picture below: That way, it seems we no longer need to depend on that website. Even if some fan’s computer suddenly crashes, he can just find any other fan to get those 2,100 photos. No more worries. Later, a virtual figure called ‘Satoshi Someone’ provides a shared folder for those photos that has a protocol; users can fetch photos from it, but they must follow the protocol. This way, every fan can get those 2,100 photos from this folder, but everyone who fetches them must follow a protocol — of course, the protocol defined by that Satoshi. ‘You may not copy, modify, or share any photo in the file. Any behavior of fans in the shared folder will be recorded, and recorded by time!’ The fans love so-and-so so much, and do not need to go to that other site to get them, so of course they eagerly join. Then one day, naughty little One wants to break the rules and delete photos numbered 1-100 at 12 noon on January 15, 2018. According to the protocol, this behavior will be recorded and broadcast to the other fans. Are the photos actually deleted? Of course not — because little Lu also has the photos in hand. After receiving the broadcast she can immediately restore the deleted photos in the shared folder. Little One will never be able to tamper with or destroy the ‘shared folder’, and all behavior is recorded in sync on other users’ computers. This is blockchain: data stored in a distributed way, decentralized. All behavior is broadcast and recorded with timestamps, and the data source cannot be modified, destroyed, or faked. Unless a million users’ computers are blown up at the same moment, or the internet disappears, or the world ends… otherwise the data will exist forever. How do you add resources protected by the blockchain? ‘Satoshi Someone’ shows up again. He says you can add photos to the file, but each of you must reach some kind of ‘consensus’. What is ‘consensus’? It is the rules we all acknowledge. So what exactly is the consensus? Ah — little One and little Lu immediately understood Satoshi’s meaning: within a set time each year, shoot 100 photos of so-and-so as fast as possible, and then they can be added to the ‘so-and-so shared folder’, and our resources expand. But the good times did not last. Satoshi noticed that if lots of people shoot, hitting the top 100 could be done quickly, and then photography would have no difficulty. And the photo quality was poor — it seemed anyone could easily add photo resources, so the quality of so-and-so’s photos could not be guaranteed. So Satoshi descends again and raises the consensus difficulty of photographing. As loyal fans, how could little One and little Lu give up? They bought high-end cameras, had so-and-so pose in all sorts of ways, and spent huge amounts of time and sweat to produce high-quality photos — and of course they themselves suffered a great deal. This way, high-quality photos can be added to ‘so-and-so’s folder’.

What is an ICO?

Little One thinks: every photo is unforgeable and indestructible, so it is unique, and it has a separate serial number — if you put a price on each photo, is it not worth money? Just like famous paintings in the real world that cannot be copied! Little One takes the previous photos of so-and-so and constructs a corresponding ‘so-and-so coin’. Of course, this behavior is similar to our government issuing equivalent RMB based on the amount of gold in the treasury. As for the valuation, of course Little One gets to decide — he is the owner of the photos, after all. To prove that one so-and-so coin is worth 50,000, Little One first buys 1,100 of the 2,100, and issues the rest to the onlookers. ‘We already bought one for 50,000, which shows it is worth that price — the remaining 1,000, let us all buy them together.’ That way, if all 2,100 are subscribed, the 2,100 so-and-so coins would be valued at 105 million. This process of obtaining financing by issuing digital currency is an ICO. According to what this picture means, if little One and little Lu are a trustworthy institution or public figures, they can still be believed — but of course there will also be many lawbreakers maliciously issuing currency to cash out. This is also why our country bans ICO issuance: currently there is no complete ICO regulatory framework that can guarantee the trustworthiness of the issuing institution and legally supervise them, so the onlookers have to bear the risk themselves and find a trustworthy institution. This way all 2,100 so-and-so coins are successfully subscribed and the fund is established — this is an ICO. Of course, the onlookers can also keep taking photos to create so-and-so coins, it is just a bit harder. Now everyone understands what blockchain and ICO are, right? Next, a hands-on guide to creating a blockchain in Python. Creating a blockchain from scratch in Python Curious about the rise of digital currency, and wanting to know how the technology behind it — blockchain — is implemented, we build a blockchain in Python here to deepen our understanding of it.

Preparation

This article assumes the reader has a basic understanding of Python, can read and write basic Python, and needs a basic understanding of HTTP requests. We know a blockchain is an immutable, ordered chain structure made of records of blocks; the records can be transactions, files, or any data you want — the important thing is that they are linked by hashes. If you are not yet familiar with hashing, you can read this article https://learncryptography.com/hash-functions/what-are-hash-functions. Environment setup: Make sure Python 3.6+, pip, Flask and requests are installed. Installation:

pip install Flask==0.12.2 requests==2.18.4

You also need an HTTP client, such as Postman, cURL or another client. Reference source code (the original code could not run when I translated it, so I forked a copy, fixed the errors in it, and added the translation; thanks for the stars).

Start creating the Blockchain

Create a new file blockchain.py; all the code in this article is written in this one file, and you can refer to the source code at any time. The Blockchain class First create a Blockchain class. In the constructor, two lists are created: one to store the blockchain, one to store transactions. Here is the framework of the Blockchain class:

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

The Blockchain class manages the chain: it can store transactions, add new blocks, and so on. Below we refine these methods further. Block structure Each block contains the attributes: index, Unix timestamp, list of transactions, proof of work (explained later), and the hash of the previous block. Here is the structure of a block:

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

By this point the concept of blockchain is clear: each new block contains the hash of the previous block — this is the key point, and it guarantees the immutability of the blockchain. If an attacker damages some earlier block, then the hashes of all the blocks after it become incorrect. If you do not get it, take your time to digest it. Adding transactions Next we need to add a transaction to refine the new_transaction method:

class Blockchain(object):
   ...
   def new_transaction(self, sender, recipient, amount):
       """
       生成新交易信息,信息将加入到下一个待挖的区块中
       :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,
           'recipient': recipient,
           'amount': amount,
       })
       return self.last_block['index'] + 1

The method appends a transaction record to the list and returns the index of the block that record will be added to (the next block to be mined). This will be useful later when users submit transactions. Creating new blocks When a Blockchain is instantiated, we need to construct a genesis block (the first block with no predecessor) and give it a proof of work. Every block needs proof of work, commonly called mining, which we will explain later. To construct the genesis block we also need to refine new_block(), new_transaction() and hash() methods:

import hashlib
import json
from time import time
class Blockchain(object):
   def __init__(self):
       self.current_transactions = []
       self.chain = []
       # Create the genesis block
       self.new_block(previous_hash=1, proof=100)
   def new_block(self, proof, previous_hash=None):
       """
       生成新块
       :param proof: <int> The proof given by the Proof of Work algorithm
       :param previous_hash: (Optional) <str> Hash of previous Block
       :return: <dict> New Block
       """
       block = {
           'index': len(self.chain) + 1,
           'timestamp': time(),
           'transactions': self.current_transactions,
           'proof': proof,
           'previous_hash': previous_hash or self.hash(self.chain[-1]),
       }
       # Reset the current list of transactions
       self.current_transactions = []
       self.chain.append(block)
       return block
   def new_transaction(self, sender, recipient, amount):
       """
       生成新交易信息,信息将加入到下一个待挖的区块中
       :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,
           'recipient': recipient,
           'amount': amount,
       })
       return self.last_block['index'] + 1
   @property
   def last_block(self):
       return self.chain[-1]
   @staticmethod
   def hash(block):
       """
       生成块的 SHA-256 hash值

       :param block: <dict> Block
       :return: <str>
       """
       # We must make sure that the Dictionary is Ordered, or we'll have inconsistent hashes
       block_string = json.dumps(block, sort_keys=True).encode()
       return hashlib.sha256(block_string).hexdigest()

The code and comments above give an intuitive understanding of blockchain. Next let us see how blocks are mined. Understanding proof of work New blocks are constructed using a proof-of-work algorithm (PoW). The goal of PoW is to find a number that satisfies certain conditions — a number that is hard to compute but easy to verify. That is the core idea of proof of work. To make it easier to understand, here is an example: Suppose the hash of the product of an integer x multiplied by another integer y must end in 0, that is hash(x * y) = ac23dc…0. Let the variable x = 5, what is the value of y? Implemented in Python as follows:

from hashlib import sha256
x = 5
y = 0  # y未知
while sha256(f'{x*y}'.encode()).hexdigest()[-1] != "0":
   y += 1
print(f'The solution is y = {y}')

The result is: y = 21, because:

hash(5 * 21) = 1253e9373e...5e3600155e860

Bitcoin uses a proof-of-work algorithm called Hashcash, which is very similar to the problem above: miners race to compute a result in order to win the right to create a block. Usually the computational difficulty is proportional to the number of specific characters the target string must have. After a miner computes the result, they receive a bitcoin reward. Of course, the result is very easy to verify on the network. Implementing proof of work Let us implement a similar PoW algorithm. The rule is: find a number p such that the hash of the string formed by concatenating it with the previous block’s proof begins with 4 zeros.

import hashlib
import json
from time import time
from uuid import uuid4
class Blockchain(object):
   ...
   def proof_of_work(self, last_proof):
       """
       简单的工作量证明:
        - 查找一个 p' 使得 hash(pp') 以4个0开头
        - p 是上一个块的证明,  p' 是当前的证明
       :param last_proof: <int>
       :return: <int>
       """
       proof = 0
       while self.valid_proof(last_proof, proof) is False:
           proof += 1
       return proof
   @staticmethod
   def valid_proof(last_proof, proof):
       """
       验证证明: 是否hash(last_proof, proof)以4个0开头?

       :param last_proof: <int> Previous Proof
       :param proof: <int> Current Proof
       :return: <bool> True if correct, False if not.
       """
       guess = f'{last_proof}{proof}'.encode()
       guess_hash = hashlib.sha256(guess).hexdigest()
       return guess_hash[:4] == "0000"

The way to gauge the algorithm’s complexity is to change the number of leading zeros. We use 4 zeros for the demo; you will find that one more zero greatly increases the time needed to compute a result. Now the Blockchain class is basically complete. Next we use HTTP requests to interact with it.

Blockchain as an API

We will use the Python Flask framework, a lightweight web application framework that conveniently maps network requests to Python functions. Now let us get the Blockchain running on Flask. We will create three endpoints:

  • /transactions/new creates a transaction and adds it to a block
  • /mine tells the server to mine a new block
  • /chain returns the whole blockchain

Creating a node Our ‘Flask server’ will play the role of one node in the blockchain network. First let us add some framework code:

import hashlib
import json
from textwrap import dedent
from time import time
from uuid import uuid4
from flask import Flask
class Blockchain(object):
   ...
# Instantiate our Node
app = Flask(__name__)
# Generate a globally unique address for this node
node_identifier = str(uuid4()).replace('-', '')
# Instantiate the Blockchain
blockchain = Blockchain()
@app.route('/mine', methods=['GET'])
def mine():
   return "We'll mine a new Block"
@app.route('/transactions/new', methods=['POST'])
def new_transaction():
   return "We'll add a new transaction"
@app.route('/chain', methods=['GET'])
def full_chain():

   response = {
       'chain': blockchain.chain,
       'length': len(blockchain.chain),
   }
   return jsonify(response), 200
if __name__ == '__main__':
   app.run(host='0.0.0.0', port=5000)

A brief explanation of the code above:

  • Line 15: creates a node.
  • Line 18: creates a random name for the node.
  • Line 21: instantiates the Blockchain class.
  • Lines 24–26: creates the /mine GET endpoint.
  • Lines 28–30: creates the /transactions/new POST endpoint; you can send transaction data to it.
  • Lines 32–38: creates the /chain endpoint, returning the whole blockchain.
  • Lines 40–41: the service runs on port 5000.

Sending a transaction The data structure of a transaction sent to the node is as follows:

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

We already have a method for adding transactions, so adding a transaction through the endpoint is very simple:

import hashlib
import json
from textwrap import dedent
from time import time
from uuid import uuid4
from flask import Flask, jsonify, request
...
@app.route('/transactions/new', methods=['POST'])
def new_transaction():
   values = request.get_json()
   # Check that the required fields are in the POST'ed data
   required = ['sender', 'recipient', 'amount']
   if not all(k in values for k in required):
       return 'Missing values', 400
   # Create a new Transaction
   index = blockchain.new_transaction(values['sender'], values['recipient'], values['amount'])
   response = {'message': f'Transaction will be added to Block {index}'}
   return jsonify(response), 201

Mining Mining is exactly where the magic is. It is simple and does the following three things:

  • Compute the proof of work, PoW.
  • Grant the miner (yourself) one coin by adding a new transaction.
  • Construct a new block and add it to the chain.

    import hashlib
    import json
    from textwrap import dedent
    from time import time
    from uuid import uuid4
    from flask import Flask, jsonify, request

    import hashlib
    import json
    from time import time
    from uuid import uuid4
    from flask import Flask, jsonify, request

    @app.route(‘/mine’, methods=[‘GET’])
    def mine():

    We run the proof of work algorithm to get the next proof…

    last_block = blockchain.last_block
    last_proof = last_block[‘proof’]
    proof = blockchain.proof_of_work(last_proof)

    给工作量证明的节点提供奖励.

    发送者为 “0” 表明是新挖出的币

    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'],
    

    }
    return jsonify(response), 200

Note that the recipient of the transaction is our own server node; most of the work we do is just interacting around the methods of the Blockchain class. At this point our blockchain is done, so let us actually run it. Running the blockchain You can use cURL or Postman to interact with the API. Start the server:

$ python blockchain.py
* Runing on http://127.0.0.1:5000/ (Press CTRL+C to quit)

Let us mine by requesting http://localhost:5000/mine: Add a new transaction through a POST request: If you are not using Postman, the following cURL command works the same:

$ curl -X POST -H "Content-Type: application/json" -d '{
"sender": "d4ee26eee15148ee92c6cd394edd974e",
"recipient": "someone-other-address",
"amount": 5
}' "http://localhost:5000/transactions/new"

After mining twice, there are 3 blocks. Requesting http://localhost:5000/chain gives you all the block information.

{
 "chain": [
   {
     "index": 1,
     "previous_hash": 1,
     "proof": 100,
     "timestamp": 1506280650.770839,
     "transactions": []
   },
   {
     "index": 2,
     "previous_hash": "c099bc...bfb7",
     "proof": 35293,
     "timestamp": 1506280664.717925,
     "transactions": [
       {
         "amount": 1,
         "recipient": "8bbcb347e0634905b0cac7955bae152b",
         "sender": "0"
       }
     ]
   },
   {
     "index": 3,

     "previous_hash": "eff91a...10f2",
     "proof": 35089,
     "timestamp": 1506280666.1086972,
     "transactions": [
       {
         "amount": 1,
         "recipient": "8bbcb347e0634905b0cac7955bae152b",
         "sender": "0"
       }
     ]
   }
 ],
 "length": 3
}

Consistency (consensus)

We now have a basic blockchain that can accept transactions and mine, but a blockchain system should be distributed. Since it is distributed, what exactly guarantees that all nodes have the same chain? That is the consistency problem. If we want multiple nodes on the network, we must implement a consensus algorithm. Registering nodes Before implementing the consensus algorithm, we need a way for a node to know its neighboring nodes. Each node needs to keep a record of the other nodes in the network, so let us add a few endpoints:

  • /nodes/register accepts a list of new nodes in URL form.
  • /nodes/resolve runs the consensus algorithm, resolves any conflicts, and ensures the node has the correct chain.

Let us modify Blockchain’s init function 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):
       """
       Add a new node to the list of nodes
       :param address: <str> Address of node. Eg. 'http://192.168.0.5:5000'
       :return: None
       """
       parsed_url = urlparse(address)
       self.nodes.add(parsed_url.netloc)

We use a set to store nodes; this is a simple way to avoid adding a node twice. Implementing the consensus algorithm As mentioned earlier, a conflict is when different nodes hold different chains. To solve this, the rule is that the longest valid 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:

...
import requests
class Blockchain(object)
   ...
   def valid_chain(self, chain):
       """
       Determine if a given blockchain is valid
       :param chain: <list> A blockchain
       :return: <bool> True if valid, False if not
       """
       last_block = chain[0]
       current_index = 1
       while current_index < len(chain):
           block = chain[current_index]
           print(f'{last_block}')
           print(f'{block}')
           print("\n-----------\n")
           # Check that the hash of the block is correct
           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):
       """
       共识算法解决冲突
       使用网络中最长的链.
       :return: <bool> True 如果链被取代, 否则为False
       """
       neighbours = self.nodes
       new_chain = None
       # We're only looking for chains longer than ours
       max_length = len(self.chain)
       # Grab and verify the chains from all the nodes in our network
       for node in neighbours:
           response = requests.get(f'http://{node}/chain')
           if response.status_code == 200:
               length = response.json()['length']
               chain = response.json()['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

The first method, valid_chain(), checks whether a chain is valid, iterating over each block and verifying the hash and proof. The second method, resolve_conflicts(), resolves conflicts by iterating over all neighbor nodes and using the previous method to check the chain’s validity; if a longer valid chain is found, it replaces its own chain. Let us add two routes, one for registering nodes and one for resolving conflicts.

@app.route('/nodes/register', methods=['POST'])
def register_nodes():
   values = request.get_json()
   nodes = values.get('nodes')
   if nodes is None:
       return "Error: Please supply a valid list of nodes", 400
   for node in nodes:
       blockchain.register_node(node)
   response = {
       'message': 'New nodes have been added',
       'total_nodes': list(blockchain.nodes),
   }
   return jsonify(response), 201
@app.route('/nodes/resolve', methods=['GET'])
def consensus():
   replaced = blockchain.resolve_conflicts()
   if replaced:
       response = {
           'message': 'Our chain was replaced',
           'new_chain': blockchain.chain
       }
   else:


       response = {
           'message': 'Our chain is authoritative',
           'chain': blockchain.chain
       }
   return jsonify(response), 200

You can run nodes on different machines, or open different network ports on one machine to simulate a multi-node network. Here we demonstrate with different ports on the same machine; running the following commands in different terminals starts two nodes:

Then mine two blocks on node 2 to make sure it has a longer chain, and then visit the /nodes/resolve endpoint on node 1 — node 1’s chain will be replaced by node 2’s chain through the consensus algorithm. All right, you can invite your friends to test your blockchain together.