In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-02 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/01 Report--
How to use Python to start to create a blockchain, for this problem, this article introduces the corresponding analysis and solutions in detail, hoping to help more partners who want to solve this problem to find a more simple and easy way.
We, who are new to the rise of digital money, want to know how the blockchain, the technology behind it, is realized.
But fully understand the blockchain is not easy, I like to learn in practice, by writing code to learn the technology will be more solid. The understanding of block chain can be deepened by constructing a block chain.
Preparatory work
This article requires readers to have a basic understanding of Python, to be able to read and write basic Python, and to have a basic understanding of HTTP requests.
We know that a blockchain is an immutable, ordered chain structure made up of chunk records, which can be transactions, files, or any data you want, and importantly, they are linked by a hash (hashes).
If you don't know much about hash, you can check out this article.
Environmental preparation
Environment preparation, make sure that Python3.6+, pip, Flask, requests installation method is installed:
Pip install Flask==0.12.2 requests==2.18.4
You also need a HTTP client, such as Postman,cURL or another client.
Refer to the source code (the original code could not run while I was translating, I fork a copy, fixed the error and added the translation, thanks to star)
Start creating Blockchain
Create a new file blockchain.py. All the code in this article is written in this file. You can refer to the source code at any time.
Blockchain class
First create a Blockchain class and create two lists in the constructor, one for storing the chunk chain and one for storing transactions.
The following is the framework for 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 is used to manage chains, it can store transactions, add new blocks, and so on. Let's further improve these methods.
Block structure
Each chunk contains attributes: index (index), Unix timestamp (timestamp), transaction list (transactions), proof of workload (explained later), and hash value of the previous chunk.
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"}
At this point, the concept of blockchain is clear. Each new block contains the Hash of the previous block, which is the key point, which ensures the immutability of the blockchain. If the attacker destroys one of the previous chunks, the Hash of all subsequent chunks will become incorrect. If you don't understand, please digest it slowly. Please refer to {% post_link whatbc block chain bookkeeping principle%}.
Join the deal
Next we need to add a transaction to refine the new_transaction method
Class Blockchain (object):... Def new_transaction (self, sender, recipient, amount): "generate new deal information The information will be added to the next block to be dug: param sender: Address of the Sender: param recipient: Address of the Recipient: param amount: Amount: return: 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
Method adds a transaction to the list and returns the index of the block to which the record will be added (the next block to be mined), which will be useful later when the user submits the transaction.
Create a new block
When the Blockchain is instantiated, we need to construct a creation block (the first block without the previous block) and add a proof of workload to it. Each block needs to be proved by workload, commonly known as mining, which will be explained later.
In order to construct Genesis blocks, we also need to refine the new_block (), new_transaction (), and hash () methods:
Import hashlibimport jsonfrom time import timeclass 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): "" generate a new block: param proof: The proof given by the Proof of Work algorithm: param previous_hash: (Optional) Hash of previous Block: return: 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): "" generate new transaction information The information will be added to the next block to be dug: param sender: Address of the Sender: param recipient: Address of the Recipient: param amount: Amount: return: 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 value of the building block: param block: Block: return:"# 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 above code and comments can give you an intuitive understanding of the blockchain, and then let's take a look at how the blockade is dug out.
Understand the proof of workload
The new block relies on the workload proof algorithm (PoW) to construct. The goal of PoW is to find a number that meets certain criteria, which is difficult to calculate but easy to verify. This is the core idea of workload proof.
To make it easier to understand, for example:
Suppose the Hash value of the product of one integer x times another integer y must end with 0, that is, hash (x * y) = ac23dc...0. Let the variable x = 5, find the value of y?
The implementation with Python is as follows:
From hashlib import sha256x = 5y = 0 # y unknown while sha256 (f'{x y} '.encode ()) .hexdigest () [- 1]! = "0": y + = 1print (f'The solution is y = {y}')
The result is yearly 21. Because:
Hash (5 * 21) = 1253e9373e...5e3600155e860
In Bitcoin, a workload proof algorithm called Hashcash is used, which is similar to the above problem. The miners scrambled to calculate the results for the right to create the block. Usually, the difficulty of calculation is proportional to the number of specific characters that the target string needs to satisfy, and the miner will be rewarded with bitcoin after calculating the result. Of course, it is very easy to verify this result on the Internet.
Implementation workload proof
Let's implement a similar PoW algorithm. The rule is to find a number p so that the Hash value of the string spliced with the proof of the previous block starts with 4 zeros.
Import hashlibimport jsonfrom time import timefrom uuid import uuid4class Blockchain (object):... Def proof_of_work (self, last_proof): simple proof of workload:-find a p'to make hash (pp') start with 4 zeros-p is the proof of the previous block P'is the current proof: param last_proof:: return: "" proof = 0 while self.valid_proof (last_proof, proof) is False: proof + = 1 return proof @ staticmethod def valid_proof (last_proof, proof): "" verify whether it is hash (last_proof) Proof) begins with 4 zeros: param last_proof: Previous Proof: param proof: Current Proof: return: 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 measure the complexity of the algorithm is to modify the number of zeros. Using four for the demonstration, you will find that one more zero will greatly increase the time it takes to calculate the results.
Now that the Blockchain class is almost complete, use HTTP requests to interact.
Blockchain as API interface
We will use the Python Flask framework, a lightweight Web application framework that makes it easy to map network requests to Python functions, and now let's have Blockchain run on Flask web.
We will create three interfaces:
/ transactions/new create a deal and add it to the block
/ mine tells the server to mine new blocks
/ chain returns the entire block chain
Create a nod
Our "Flask server" will act as a node in the blockchain network. Let's add some framework code first:
Import hashlibimport jsonfrom textwrap import dedentfrom time import timefrom uuid import uuid4from flask import Flaskclass Blockchain (object):... # Instantiate our Nodeapp = Flask (_ _ name__) # Generate a globally unique address for this nodenode_identifier = str (uuid4 ()). Replace ('-',') # Instantiate the Blockchainblockchain = 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), 200if _ _ name__ = =' _ main__': app.run (host='0.0.0.0', port=5000)
Briefly explain the above code: line 15: create a node. Line 18: create a random name for the node. Line 21: instance Blockchain class. Lines 24-26: create the / mine GET interface. Line 28-30: create / transactions/new POST interface to send transaction data to the interface. Lines 32-38: create the / chain interface and return the entire blockchain. Line 40-41: the service runs on port 5000.
Send a deal
The transaction data sent to the node is structured as follows:
{"sender": "my address", "recipient": "someone else's address", "amount": 5}
There is already a way to add a transaction, and it is very simple to add a transaction based on the interface
Import hashlibimport jsonfrom textwrap import dedentfrom time import timefrom uuid import uuid4from 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 is the magic. It's very simple. It does three things:
Proof of calculation workload PoW
Grant the miner (himself) a coin by adding a new deal
Construct a new block and add it to the chain
Import hashlibimport jsonfrom time import timefrom uuid import uuid4from 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) # provides rewards for nodes with proof of workload. # Sender "0" indicates that it is newly dug up 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, and most of the work we do is around the interaction of Blockchain class methods. At this point, even if our block chain is complete, let's actually run it.
Running block chain
You can use cURL or Postman to interact with API
Start server:
$python blockchain.py* Runing on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Let's dig the mine by requesting http://localhost:5000/mine.
Add a new deal through a post request
If you are not using Postman, the following cURL statement is 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 digging two mines, there are three blocks, and all the block information can be obtained by requesting http://localhost:5000/chain.
{"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 already have a basic block chain that can accept trading and mining. But the blockchain system should be distributed. Since it is distributed, how on earth can we ensure that all nodes have the same chain? This is the consistency problem. If we want to have multiple nodes on the network, we must implement a consistent algorithm.
Register node
Before implementing the consistency algorithm, we need to find a way to let a node know its neighboring nodes. Each node needs to keep a record that contains other nodes in the network. So let's add a few interfaces:
/ nodes/register receives a list of new nodes in URL form
/ nodes/resolve executes the consistency algorithm to resolve any conflicts and ensure that the node has the correct chain
Let's modify the init function of Blockchain and provide a method to register the node:
... 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: Address of node. Eg. 'http://192.168.0.5:5000': return: None" parsed_url = urlparse (address) self.nodes.add (parsed_url.netloc)
We use set to store nodes, which is an easy way to avoid adding nodes repeatedly.
Implementation of consensus algorithm
As mentioned earlier, conflict means that different nodes have different chains. in order to solve this problem, it is stipulated that the longest and effective chain is the final chain, in other words, the effective longest chain in the network is the actual chain.
Let's use the algorithm below to reach a consensus in the network.
... import requestsclass Blockchain (object)... Def valid_chain (self, chain): "Determine if a given blockchain is valid: param chain: a blockchain: return: 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: 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 (), is used to check whether it is a valid chain, traversing each block to verify hash and proof.
The second method, resolve_conflicts (), is used to resolve conflicts, traversing all neighboring nodes, and using the previous method to check the validity of the chain. * * if you find a valid longer chain, replace your own chain * *
Let's add two routes, one to register the node and one to resolve the conflict.
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, open different ports on the same machine to demonstrate, run commands on different terminals, and start two nodes: http://localhost:5000 and http://localhost:5001.
This is the answer to the pipenv run python blockchain.pypipenv run python blockchain.py-p 5001 question on how to start creating a blockchain with Python. I hope the above content can be of some help to you. If you still have a lot of doubts to be solved, you can follow the industry information channel for more related knowledge.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.