Create your own blockchain amp; cryptocurrency! - understand blockchains by creating one in python
What exactly is a blockchain?
- How does a blockchain work?
- What is Bitcoin or STEEM exactly?
- How does a blockchain make sure of its correctness
- What is?mining?exactly?
These are only some questions, probably many of you are asking yourselves.
I'm here to provide you with kind of an unusual answer.
My goal is to help you undestand the whole system behind blockchains, by actually creating a small blockchain yourself!
With the rise of cryptocurrencies and decentralized systems like Bitcoin or STEEM, many people want to really undestand, what this is all about. I will show you how the system works, by coding a blockchain from scratch in python with you. The guide will be mainly for Windows, but I will also add comments regarding Linux. You don't know a whole of python, to follow this guide, but it is advised to know the most basic basics.
Get ready
Setup Python and pip
First off, we need to install Python 3.6+ along with pip, with which you can install python packages.
- On?Linux, you can install python, by simply typing?sudo apt-get install python3.6?into the terminal. If you encounter errors, please try?sudo apt-get update?and then try to execute the command again. If it still doesn't work, please search for installation instructions for your specific system on your preferred search engine.
- On?Windows,
- first download the binary, that suits your system best, under the?official python download page for windows.. Make sure you grab at least the?version 3.6?or higher.
- Install the file you just downloaded. Make sure you check the option to install pip, when provided with an option to do so. If not, don't worry, it probably is enabled by default.
IDE or not?
As a next step, you want to decide, whether to utilize an?IDE?or not. An IDE is an environment, which supports you in the creation process of your application, by providing many features, with for example syntax highlighting, or code completion, to name just 2 possible features. My favorite IDE for Python development is probably PyCharm, which you can fetch from?this link.?Setting up PyCharm on Windows is as simple, as downloading the executable installer and installing it with the provided setup utility. PyCharm is free tu use, as long as you use the Community Edition.
You can also use your coding notepad of choice. We will only work in one file, which you have to execute, so as long as your text-editing software is able to produce files with the ending?.py, it will work fine.
Setup your workspace (PyCharm)
If you decided to use PyCharm, simply open it up and click on?Create Project?in the popup dialogue. In the next dialogue you want to specify your project's name. I chose to use?MyBlockChain?as my project name. Finally click on?create?in the bottom right corner. On your left hand side, you're now provided with a file tree.
Create your file (Simple Text Editor)
If you use a simple text editor, just create a file anywhere you like with the file extension?.py. In my case I chose to use the filename?MyBlockChain.py.
Install the needed packages
PyCharm
In PyCharm you can install packages very easily and add them to your project:
Pip
If you chose not to use PyCharm, you simply need to open up the terminal on linux or the command prompt, or PowerShell on Windows?(simply press?Windows+R?and type in cmd)?and then execute?pip install Flask==0.12.2 requests==2.18.4. If this gives you an error, please double check that you have?pip?installed. If the problem still occurs, please troubleshoot the error message using google, as there are too many possibilities, what the error could be caused by, for me to discuss every one of them here.
Getting a HTTP-Client
You will also need a HTTP-Client, as we need to make?GET?and?POSTrequests to our Flask instance, at some Point in time. Mainly, there are two options -?Postman?or?cURL. I highly recommend?Postman, as it is easy and intuitive to use, but if you just want a simple and quick solution, without having to register for an account, just use?cURL. Online solutions, probably won't work, as the webserver you are going to be trying to access, is just on your local machine.
Just gimme the source code!
If you just want the source code and don't want to follow my instructions, please scroll down, to the very end of this post, where I will add the source code in its complete beauty.
The Blockchain - Your Blockchain
Step 1: Creating a simplistic Blockchain
A block chain is basically a chain of blocks that are linked together in some way, as you have already figured. In this case, every block contains a hash of the previous block. A hash is a hexadecimal number that is determined by a specific algorithm. Imagine a hash being a digital fingerprint of an item. A good hash algorithm will never return the same hash for two different items, so every hash is individual. In our case we will be using the?SHA-256?algorithm. Furthermore the hash algorithm is not reversible, so you can't determine the object, by having its hash, but you can always apply the hash algorithm on the object, to get its hash. As every item has the hash of its previous item, the blockchain is protected against violation, as one would have to change every following block, as the hash changes with every change, as two different items can't have the same hash.
The Blockchain class
Our Blockchain class basically consists of a constructor and some functions. In the constructor, we will create two empty lists - one to store our blockchain in and another, for our transactions. As for now, our class will have several functions:
- A function to create new blocks
- A function to create new transactions
- A function, which hashes a block
- A function to fetch the last block
The python template looks like this:
Step 2: The blocks
As described earlier, a blockchain consists of blocks. So I will cover them first.
Each Block has 5 fields:
- An index,
- an Unix timestamp,
- a list of transactions,
- a proof,
- and finally the hash of the previous block.
Just to clarify things, here is an example of a block
Step 3: Hashing it
As every block needs the hash of the previous block, we need a function, that calculates the hash of a block. To accomplish this, we simply modify our empty?hash?function
import hashlib import jsonclass MyBlockChain(object):[...]@staticmethoddef hash(block):"""This function hashes the block using the SHA-256 hash algorithmThe function is given a block and returns a string, consisting of the hash:param block: <dict> Block:return: <str>"""# As every change in an item changes the hash, we first have to do a little sort operation, or else we would get inconsistent hashesblock_sorted = json.dumps(block, sort_keys=True).encode()return hashlib.sha256(block_sorted).hexdigest()Step 4: Transactions
Our?create_new_transaction?method is responsible for adding new transactions to the?transactions?list, which will then be stored inside a block. The whole function is pretty self explanatory. But first we need a function to return the last block of the chain, as we will calculate the new index, at which the transaction will be stored, by increasing the index of the last block by 1
class MyBlockChain(object):[...]@propertydef last_block(self):return self.blockchain[-1]Now we can fill out the?create_new_transaction?function
class MyBlockChain(object):[...]def create_new_transaction(self, sender, recipient, amount):"""This function creates a new transaction that will then be placed in a new block, alone or bundled together with other transactions.:param sender: <str> Sender's address:param recipient: <str> Recipient's address:param amount: <int> Amount to be transferred:return: <int> This is the index of the block that will contain this transaction"""self.transactions.append({'sender': sender,'recipient': recipient,'amount': amount,})return self.last_block['index'] + 1Step 5: Creating new Blocks
By now we almost have everything at our hands, what we need in order to make a new block. The only thing missing is the?proof?field. As this is a little harder to understand, I will explain it later.
But we still have one problem - if every block has the hash of the previous block, what shall we do with our first block, as there is no previous block for us to hash.
This first block is called the?genesis?block.
Step 6: What's up with the proof?!
The?Proof of Work (PoW) algorithm
This system wants to?proof?that work has been done. Now a little bit less abstract. Basically we are searching for a number that matches a specific criteria. The thing is, for the system to work, the process of finding a number matching the criteria has to be?difficult, but the verification process has to be?quick and easy. This is how new blocks are created, or expressed in another, more commonly used term,?mined.
Still too abstract? Ok here is an example:
We are looking for a hash of a product of two integers that ends with a 1.
So the result of the multiplication of?a?and?b?gets hashed and has to end with a 1. If we set a to?a?static value, our algorithm will determine a value for?b, for which this criteria is matched.
This example outputs
The solution is b = 4This means that the hash of?12*4?ends with a 1
hash(48) = 98010bd9270f9b100b6214a21754fd33bdc8d41b2bc9f9dd16ff54d3c34ffd71As you can tell, the verification process doesn't need countless loops, until it finds a matching pair. You just have to run the hash algorithm once on the numbers and you can easily determine, whether the numbers match the criteria, or not.
Step 7: Implementing PoW
Firstoff, we need a criteria, or commonly referred to as a rule. For now, our rule is that the hash has to have 5 leading zeroes, so?000005bc845e...would be a valid result, but?000019ea76c4?would not. As the difficulty rises extremely, if we would require 6 leading zeros, the difficulty of our simple algorithm can be adjusted by changing the amount of leading zeroes required. This is the implementation in python:
[...] from uuid import uuid4class MyBlockChain(object):[...]def pow(self, last_proof):"""Simple PoW Algorithm:- Find a number y, so that hash(xy) starts with 5 zeroes. x is the last y aka last_proof. y is then the new proof.:param last_proof: <int>:return: <int>"""current_proof = 0while self.validate_proof(last_proof, current_proof) is False:current_proof += 1return current_proof@staticmethoddef validate_proof(last_proof, current_proof):"""Returns, whether the hash of the lastproof and the current_proof contains 5 leading zeroes.:param last_proof: <int> Previous Proof Number:param current_proof: <int> Current Proof Number:return: <bool>"""possible_hash = hashlib.sha256(f'{last_proof}{current_proof}'.encode()).hexdigest()return possible_hash[:5] == "00000"Step 8: Interacting with our class
Now we are able to create a blockchain. But we can't really interact with it, as we have only interacted with the functions and variables of our class.
We are going to use HTTP requests to interact with our blockchain. So let's set it up!
HTTP in the house!
To talk to our blockchain using Http requests, we need some help - which comes in the form of the?Flask Framework. We will create and implement 3 basic methods for now:
- /blockchain?to retrieve the full blockchain
- /mining?to make our simple server mine a block
- /transactions/add?to add a new transaction to the blockchain.
Step 9: Flask
First we need to implement Flask. Here is the code:
[...] from textwrap import dedent from flask import Flask, jsonify, requestclass MyBlockChain(object):[...]app = Flask(__name__) node_identifier = str(uuid4()).replace('-', '')myblockchain = MyBlockChain()@app.route('/blockchain', methods=['GET']) def get_full_chain():output = {'chain': myblockchain.blockchain,'length': len(myblockchain.blockchain),}return jsonify(output), 200@app.route('/mining', methods=['GET']) def mining():pass @app.route('/transactions/add', methods=['POST']) def add_transaction():pass if __name__ == '__main__':app.run(host='0.0.0.0', port=5000)Step 10: Adding Transactions
As this is commonly the main task of a block chain and also required for a new block, I will cover this first. The user sends a?POST request?to?/transactions/add?with a JSON object, containing all required fields. This is an example, for a possible, valid request:
{"sender": "154d8554f9541e12354e1234f512a001","recipient": "8654e21254c6512a51bce156542d1e5c","amount": 212 }As you can see, a request has three fields:
- A?sender?field, with the sender id,
- a?recipient?field, with the recipient id
- and an amount, which defines how many units are to be transferred
Now we just need to implement this function
This function simply calls the?create_new_transaction?method with the parameters of the POST request
Step 11: Setup your mines
As discussed earlier, future blocks have to be mined. If a new block is found/mined, all pending transactions are added to this block. To 'mine' a new block, our function hast to do three things
(The fact that the recipient is our current node, will make more sense, as we will talk about decentralization later on.)
Hello World!
Now,?finally?we will be interacting with our blockchain API. Grab your HTTP client of choice and get going! I will explain the procedure for Postman and cURL.
Step 12: Start up the chain
First off fire up your server.
In PyCharm simply click on?Run?->?Run...?and select?[your filename].py?as the file to run, in my case?myblockchain.py.
If you chose to use a simple python file without an IDE, fire up a terminal or command prompt window inside the directory your file is located in and execute the following command
as a result you will see something similar to this
$ python blockchain.py * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)Note that you may be prompted with a dialogue of your firewall. Just accept it.
Step 13: Mining it all!
Ok let's try the most exciting thing first,?mining. I'm sure you can't wait to mine your first block, so let's do it!
As you can see in the code
we will be interacting with the?mining?part of our API through?GETrequests. This makes sense, as our only goal with this part of the API is, to mine a new block. We don't have to pass anything to the function at all, so a?GET?request is the way to go.
Postman
If you chose to use Postman, here is a quick tutorial on how to make a post request.
cURL
If you chose to use cURL as your HTTP client, simply type?curl -i -H "Content-Type: application/json" -X GET http://localhost:5000/mining?in a terminal window
Either way
With both methods you should see something similar to this as a result
{"index": 2,"message": "New Block Forged","previous_hash": "0f9cb2f06100899cb31b85fef221e243d1088c0aa6840a568e58d4a27dbd186a","proof": 888273,"transactions": [{"amount": 1,"recipient": "491002ea048a42609d967027cc46a07b","sender": "0"}] }Step 14: Transactions are great!
As our mining algorithm seems to be working fine, let's create a new transaction, to be stored in a fresh mined block. To do that in
Postman
cURL
Just execute?curl -X POST -H "Content-Type: application/json" -d '{"sender": "your-node-address", "recipient": "another-node-address", "amount": 212}' "http://localhost:5000/transactions/add"?in a terminal window.
In both cases
Replace?your-node-address?with the?recipient?address from you mining request, as this is your node address. You can also select any other 32 digit hexadezimal number, for now. Furthermore replace?another-node-address?with a random 32 digit hexadezimal number for now, as we currently don't have any other nodes.
Adjust the?amount?to your liking.
And?voilà! You have registered your first transaction!
Step 15: The Chain...
So let's inspect our chain! If you're using
Postman
Click on the?get whole blockchain?request in the left sidebar and simply enter?http://localhost:5000/blockchain?in the?Enter request URL?text field, as?GET?should be preselected. If not, please change it to the?GET?option.
cURL
just execute?curl -i -H "Content-Type: application/json" -X GET http://localhost:5000/blockchain?in a terminal window.
Either way
you should get your whole blockchain in form of a JSON-Object. In my case, my blockchain looks like this, after mining 2 times, adding 3 transactions and mining another block:
{"chain": [{"index": 1,"previous_hash": "1","proof": 100,"timestamp": 1515156902.4502413,"transactions": []},{"index": 2,"previous_hash": "0f9cb2f06100899cb31b85fef221e243d1088c0aa6840a568e58d4a27dbd186a","proof": 888273,"timestamp": 1515156913.2686973,"transactions": [{"amount": 1,"recipient": "491002ea048a42609d967027cc46a07b","sender": "0"}]},{"index": 3,"previous_hash": "1d2ae4a41f4a82ce6f04944e8227bf9c4d951d560f8763b910d7314634dfe09c","proof": 1156297,"timestamp": 1515158367.3596537,"transactions": [{"amount": 212,"recipient": "d4ee26eee15148ee92c6cd394edd974e","sender": "491002ea048a42609d967027cc46a07b"},{"amount": 212,"recipient": "5654c5654e1b551a65e15f5e4651c156","sender": "491002ea048a42609d967027cc46a07b"},{"amount": 111,"recipient": "491002ea048a42609d967027cc46a07b","sender": "5654c5654e1b551a65e15f5e4651c156"},{"amount": 1,"recipient": "491002ea048a42609d967027cc46a07b","sender": "0"}]}],"length": 3 }Decentralizing it
Ok, so we got a blockchain, that's working fine and we can interact with it. But one very important thing is still missing:?Decentralization.
This is a core element of the blockchain idea.
First off by decentralizing the whole thing, safety and integrity of the blockchain is guaranteed, as a change in the blockchain will be recognized, by the other nodes, as they also have a copy of the blockchain, and discarded.
The second reason is that we somehow have to make sense of our transactions. For this we need other nodes and why shouldn't they contribute to our network, by being a part of the blockchain system?!
But we still have a conflict there: What if a node has a blockchain that differs from all the others?
For our simple blockchain we will always make the?longest valid?blockchain authorative.
Step 16: Someone out there?!
But first things first.
To get started, we first have to implement other nodes into our system.
To accomplish this task, we have to adjust a few things in our API. First off, we are going to implement some new endpoints:
To do this, we have to modify our Blockchain class first:
Step 17: We need Consensus
To resolve the conflict of differing blockchains between the nodes, we are going to implement a consensus algorithm. As we discussed earlier, we are always utilizing the longest valid blockchain.
First we are implementing a function that validates a blockchain:
Now we just have to run every blockchain in our surrounding network through this consensus algorithm:
[...]class MyBlockChain(object)[...]def resolve(self):"""This algorithm resolves conflicts between our nodes. It is the consensus algorithm which I mentioned previously.:return: <bool> Returns true, if our chain was substituted with an updated version"""surrounding_nodes = self.nodesupdated_chain = None# If we follow our consensus algorithm description, we only want blockchains that are longer, than our current chainmax_length = len(self.blockchain)# Iterate every surrounding nodes in our network through the consensus algorithm, which means checking if the node's blockchain is longer than our current blockchain and valid and set it as our new blockchain and continue checking, as there could be an even longer and valid blockchain.for node_iterator in surrounding_nodes:response = requests.get(f'http://{node_iterator}/blockchain')if response.status_code == 200:length = response.json()['length']chain_iterator = response.json()['chain']if length > max_length and self.validate_blockchain(chain_iterator):max_length = lengthupdated_chain = chain_iterator# If we found a new blockchain, replace our current blockchain with the new oneif updated_chain:self.blockchain = updated_chainreturn Truereturn FalseNow we just have to register our new functions as new endpoints in the API:
@app.route('/nodes/add', methods=['POST']) def add_nodes():values = request.get_json()nodes = values.get('nodes')if nodes is None:return "You didn't post a valid list of nodes. Please double check your input!", 400for node in nodes:myblockchain.add_node(node)response = {'message': 'All of your specified nodes have been added to the network!','total_nodes': list(myblockchain.nodes),}return jsonify(response), 201@app.route('/nodes/resolve', methods=['GET']) def consensus():replaced = myblockchain.resolve()if replaced:response = {'message': 'There was a longer valid chain within the network. The blockchain of this node has been replaced.','new_chain': myblockchain.blockchain}else:response = {'message': 'The blockchain of this node is already the longest valid chain within the network.','chain': myblockchain.blockchain}return jsonify(response), 200Step 18: Friends are great. Even if they're virtual...
To test our decentralization algorithms, either grab some friends, to run some nodes for you, or just run the same program on different ports, so you would have to start up an instance of our blockchain-program, then change to port to 5001 for example, save, fire up an instance of this?modified?program, change the port to 5002, etc.
Step 19: Add them to your friends list
If you got some instances, you just have to register them. To do this, simply send a?POST?request with the following content
{"nodes": ["http://[ip-of-another-node-or-127.0.0.1-for-your-local-machine]:[the-port-number]"] }to?http://[the-node-ip-you-want-to-register-it-to]:[port]/nodes/add
Step 20: Consensus check
After that try to mine some blocks and even add some transactions on let's say node 2 and then run?http://[a-node-ip]:[port]/nodes/resolve?on let's say node 1. The consensus algorithm should step into action and update the blockchain of node 1.
The whole thang
I keep my promises
import hashlib import json import requests from time import time from uuid import uuid4 from textwrap import dedent from flask import Flask, jsonify, request from urllib.parse import urlparseclass MyBlockChain(object):def __init__(self):self.blockchain = []self.transactions = []# Creation of the mentioned genesis blockself.create_new_block(previous_hash=1, proof=100)self.nodes = set()def create_new_block(self, proof, previous_hash=None):"""Creates a new block and adds it to the blockchain:param proof: <int> This is generated by the proof of work algorithm:param previous_hash: (Optional) <str> Hash of the preleading Block:return: <dict> Return the new block"""new_block = {'index': len(self.blockchain) + 1,'timestamp': time(),'transactions': self.transactions,'proof': proof,'previous_hash': previous_hash or self.hash(self.blockchain[-1]),}# As all pending transactions have been processed and added to the block, the list can be resettedself.transactions = []# Add the new block to the blockchainself.blockchain.append(new_block)return new_blockdef create_new_transaction(self, sender, recipient, amount):"""This function creates a new transaction that will then be placed in a new block, alone or bundled together with other transactions.:param sender: <str> Sender's address:param recipient: <str> Recipient's address:param amount: <int> Amount to be transferred:return: <int> This is the index of the block that will contain this transaction"""self.transactions.append({'sender': sender,'recipient': recipient,'amount': amount,})return self.last_block['index'] + 1@staticmethoddef hash(block):"""This function hashes the block using the SHA-256 hash algorithmThe function is given a block and returns a string, consisting of the hash:param block: <dict> Block:return: <str>"""# As every change in an item changes the hash, we first have to do a little sort operation, or else we would get inconsistent hashesblock_sorted = json.dumps(block, sort_keys=True).encode()return hashlib.sha256(block_sorted).hexdigest()@propertydef last_block(self):return self.blockchain[-1]def pow(self, last_proof):"""Simple PoW Algorithm:- Find a number y, so that hash(xy) starts with 5 zeroes. x is the last y aka last_proof. y is then the new proof.:param last_proof: <int>:return: <int>"""current_proof = 0while self.validate_proof(last_proof, current_proof) is False:current_proof += 1return current_proof@staticmethoddef validate_proof(last_proof, current_proof):"""Returns, whether the hash of the lastproof and the current_proof contains 5 leading zeroes.:param last_proof: <int> Previous Proof Number:param current_proof: <int> Current Proof Number:return: <bool>"""possible_hash = hashlib.sha256(f'{last_proof}{current_proof}'.encode()).hexdigest()return possible_hash[:5] == "00000"def add_node(self, address):"""Register a new node:param address: <str> This is the new node's address, for example 'http://192.168.1.112:5000':return: None"""node_url = urlparse(address)self.nodes.add(node_url.netloc)def validate_blockchain(self, test_chain):"""Evaluate, whether a blockchain is valid:param chain: <list> The blockchain that shall be tested:return: <bool> Returns true if the blockchain is valid"""last_block = test_chain[0]current_index = 1while current_index < len(test_chain):block = test_chain[current_index]# Determine, whether the hash is correctif block['previous_hash'] != self.hash(last_block):return False# Determine, wheter the proof of work is correctif not self.validate_proof(last_block['proof'], block['proof']):return Falselast_block = blockcurrent_index += 1return Truedef resolve(self):"""This algorithm resolves conflicts between our nodes. It is the consensus algorithm which I mentioned previously.:return: <bool> Returns true, if our chain was substituted with an updated version"""surrounding_nodes = self.nodesupdated_chain = None# If we follow our consensus algorithm description, we only want blockchains that are longer, than our current chainmax_length = len(self.blockchain)# Iterate every surrounding nodes in our network through the consensus algorithm, which means checking if the node's blockchain is longer than our current blockchain and valid and set it as our new blockchain and continue checking, as there could be an even longer and valid blockchain.for node_iterator in surrounding_nodes:response = requests.get(f'http://{node_iterator}/blockchain')if response.status_code == 200:length = response.json()['length']chain_iterator = response.json()['chain']if length > max_length and self.validate_blockchain(chain_iterator):max_length = lengthupdated_chain = chain_iterator# If we found a new blockchain, replace our current blockchain with the new oneif updated_chain:self.blockchain = updated_chainreturn Truereturn Falseapp = Flask(__name__) node_identifier = str(uuid4()).replace('-', '')myblockchain = MyBlockChain()@app.route('/blockchain', methods=['GET']) def get_full_chain():output = {'chain': myblockchain.blockchain,'length': len(myblockchain.blockchain),}return jsonify(output), 200@app.route('/mining', methods=['GET']) def mining():# Calculate the new proof by using our PoW algorithmlast_block = myblockchain.last_blocklast_proof = last_block['proof']proof = myblockchain.pow(last_proof)# For finding/mining the proof, the miner is granted a reward# The sender is nobody, as this coin is coming out of the voidmyblockchain.create_new_transaction(sender="0",recipient=node_identifier,amount=1,)# Add the new created block to the chainprevious_hash = myblockchain.hash(last_block)newblock = myblockchain.create_new_block(proof, previous_hash)output = {'message': "A new block was mined",'index': newblock['index'],'transactions': newblock['transactions'],'proof': newblock['proof'],'previous_hash': newblock['previous_hash'],}return jsonify(output), 200@app.route('/transactions/add', methods=['POST']) def add_transaction():values = request.get_json()# The POST request has to have the following required fieldsrequired = ['sender', 'recipient', 'amount']if not all(k in values for k in required):return 'There are values missing', 400# Adds a new transaction by utilizing our functionindex = myblockchain.create_new_transaction(values['sender'], values['recipient'], values['amount'])output = {'message': f'Your registered Transaction is going to be a part of the block with the index of {index}'}return jsonify(output), 201@app.route('/nodes/add', methods=['POST']) def add_nodes():values = request.get_json()nodes = values.get('nodes')if nodes is None:return "You didn't post a valid list of nodes. Please double check your input!", 400for node in nodes:myblockchain.add_node(node)response = {'message': 'All of your specified nodes have been added to the network!','total_nodes': list(myblockchain.nodes),}return jsonify(response), 201@app.route('/nodes/resolve', methods=['GET']) def consensus():replaced = myblockchain.resolve()if replaced:response = {'message': 'There was a longer valid chain within the network. The blockchain of this node has been replaced.','new_chain': myblockchain.blockchain}else:response = {'message': 'The blockchain of this node is already the longest valid chain within the network.','chain': myblockchain.blockchain}return jsonify(response), 200if __name__ == '__main__':app.run(host='0.0.0.0', port=5000)Final thoughts
And there you have it!
Your very own blockchain. Wasn't very hard, was it?
I sincerely hope you had fun thorughout this tutorial and were able to understand the concept and system behind it better. If you have any questions, please ask them in the comments and I'll try my best to answer them.
The obligatory begging
As this whole tutorial took me over 2 days to finish, I would love to see a lot of comments and feedback under this post. Also if you find any typos, grammar mistakes, etc. and care to tell me, i would be mor than happy about it, as English is not my native language. So please excuse any mistakes I made. I tried my very best.
Of course please upvote, if you worship my effort to enrich the community, and if you want to see more such content, consider following me.
I wish you only the best - See ya!
https://steemit.com/steemit/@dustvoice/create-your-own-blockchain-and-cryptocurrency-understand-blockchains-by-creating-one-in-python-no-knowledge-required
總結
以上是生活随笔為你收集整理的Create your own blockchain amp; cryptocurrency! - understand blockchains by creating one in python的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Learn Blockchains by
- 下一篇: android WebView详解,常见