1. 程式人生 > >Learn Blockchains by Building One

Learn Blockchains by Building One

Step 2: Our Blockchain as an API

We’re going to use the Python Flask Framework. It’s a micro-framework and it makes it easy to map endpoints to Python functions. This allows us talk to our blockchain over the web using HTTP requests.

We’ll create three methods:

  • /transactions/new to create a new transaction to a block
  • /mine to tell our server to mine a new block.
  • /chain to return the full Blockchain.

Setting up Flask

Our “server” will form a single node in our blockchain network. Let’s create some boilerplate code:

A brief explanation of what we’ve added above:

  • Line 15: Instantiates our Node. Read more about Flask here.
  • Line 18: Create a random name for our node.
  • Line 21: Instantiate our Blockchain class.
  • Line 24–26: Create the /mine endpoint, which is a GET request.
  • Line 28–30: Create the /transactions/new endpoint, which is a POST request, since we’ll be sending data to it.
  • Line 32–38: Create the /chain endpoint, which returns the full Blockchain.
  • Line 40–41: Runs the server on port 5000.

The Transactions Endpoint

This is what the request for a transaction will look like. It’s what the user sends to the server:

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

Since we already have our class method for adding transactions to a block, the rest is easy. Let’s write the function for adding transactions:

A method for creating Transactions

The Mining Endpoint

Our mining endpoint is where the magic happens, and it’s easy. It has to do three things:

  1. Calculate the Proof of Work
  2. Reward the miner (us) by adding a transaction granting us 1 coin
  3. Forge the new Block by adding it to the chain

Note that the recipient of the mined block is the address of our node. And most of what we’ve done here is just interact with the methods on our Blockchain class. At this point, we’re done, and can start interacting with our blockchain.

Step 3: Interacting with our Blockchain

You can use plain old cURL or Postman to interact with our API over a network.

Fire up the server:

$ python blockchain.py

Let’s try mining a block by making a GET request to http://localhost:5000/mine:

Using Postman to make a GET request

Let’s create a new transaction by making a POST request tohttp://localhost:5000/transactions/new with a body containing our transaction structure:

Using Postman to make a POST request

If you aren’t using Postman, then you can make the equivalent request using cURL:

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

I restarted my server, and mined two blocks, to give 3 in total. Let’s inspect the full chain by requesting :

{  "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}

Step 4: Consensus

This is very cool. We’ve got a basic Blockchain that accepts transactions and allows us to mine new Blocks. But the whole point of Blockchains is that they should be decentralized. And if they’re decentralized, how on earth do we ensure that they all reflect the same chain? This is called the problem of Consensus, and we’ll have to implement a Consensus Algorithm if we want more than one node in our network.

Registering new Nodes

Before we can implement a Consensus Algorithm, we need a way to let a node know about neighbouring nodes on the network. Each node on our network should keep a registry of other nodes on the network. Thus, we’ll need some more endpoints:

  1. /nodes/register to accept a list of new nodes in the form of URLs.
  2. /nodes/resolve to implement our Consensus Algorithm, which resolves any conflicts—to ensure a node has the correct chain.

We’ll need to modify our Blockchain’s constructor and provide a method for registering nodes:

A method for adding neighbouring nodes to our Network

Note that we’ve used a set() to hold the list of nodes. This is a cheap way of ensuring that the addition of new nodes is idempotent—meaning that no matter how many times we add a specific node, it appears exactly once.

Implementing the Consensus Algorithm

As mentioned, a conflict is when one node has a different chain to another node. To resolve this, we’ll make the rule that the longest valid chain is authoritative. In other words, the longest chain on the network is the de-facto one. Using this algorithm, we reach Consensus amongst the nodes in our network.

The first method valid_chain() is responsible for checking if a chain is valid by looping through each block and verifying both the hash and the proof.

resolve_conflicts() is a method which loops through all our neighbouring nodes, downloads their chains and verifies them using the above method. If a valid chain is found, whose length is greater than ours, we replace ours.

Let’s register the two endpoints to our API, one for adding neighbouring nodes and the another for resolving conflicts:

At this point you can grab a different machine if you like, and spin up different nodes on your network. Or spin up processes using different ports on the same machine. I spun up another node on my machine, on a different port, and registered it with my current node. Thus, I have two nodes: and http://localhost:5001.

Registering a new Node

I then mined some new Blocks on node 2, to ensure the chain was longer. Afterward, I called GET /nodes/resolve on node 1, where the chain was replaced by the Consensus Algorithm:

Consensus Algorithm at Work

And that’s a wrap... Go get some friends together to help test out your Blockchain.