Maison > Article > développement back-end > Blockchain avec Vue, Python et Flask
Création d'une application blockchain complète avec un frontend Vue.js et un backend Python.
Décrivons les composants de base et fournissons quelques exemples d'extraits de code pour vous aider à démarrer.
pip install Flask
# blockchain.py import hashlib import json from time import time from flask import Flask, jsonify, request class Blockchain: def __init__(self): self.chain = [] self.current_transactions = [] self.new_block(previous_hash='1', proof=100) 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() @property def last_block(self): return self.chain[-1] app = Flask(__name__) blockchain = Blockchain() @app.route('/mine', methods=['POST']) def mine(): values = request.get_json() required = ['proof', 'sender', 'recipient'] if not all(k in values for k in required): return 'Missing values', 400 index = blockchain.new_transaction(values['sender'], values['recipient'], values['amount']) blockchain.new_block(values['proof']) response = { 'message': f'New Block Forged', 'index': index, 'block': blockchain.last_block, } return jsonify(response), 200 @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(debug=True)
Étape 2 : Configuration du frontend
vue create my-blockchain-app
npm install axios
// src/components/Blockchain.vue <template> <div> <h1>Blockchain</h1> <button @click="fetchChain">Fetch Blockchain</button> <ul> <li v-for="block in blockchain" :key="block.index"> Block #{{ block.index }} - {{ block.timestamp }} </li> </ul> </div> </template> <script> import axios from 'axios'; export default { data() { return { blockchain: [] }; }, methods: { fetchChain() { axios.get('http://localhost:5000/chain') .then(response => { this.blockchain = response.data.chain; }) .catch(error => { console.error(error); }); } } }; </script>
Exécutez le backend Flask : assurez-vous que votre serveur Python est en cours d'exécution :
python blockchain.py
Exécutez le frontend Vue.js : maintenant, exécutez votre application Vue.js :
npm run serve
Améliorons l'application blockchain en ajoutant des fonctionnalités plus avancées telles que :
# blockchain.py import hashlib import json from time import time from flask import Flask, jsonify, request from urllib.parse import urlparse import requests class Blockchain: def __init__(self): self.chain = [] self.current_transactions = [] self.nodes = set() self.new_block(previous_hash='1', proof=100) 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() @property def last_block(self): return self.chain[-1] def proof_of_work(self, last_proof): proof = 0 while not self.valid_proof(last_proof, proof): proof += 1 return proof @staticmethod def valid_proof(last_proof, proof): guess = f'{last_proof}{proof}'.encode() guess_hash = hashlib.sha256(guess).hexdigest() return guess_hash[:4] == "0000" # Adjust difficulty here def register_node(self, address): parsed_url = urlparse(address) self.nodes.add(parsed_url.netloc) def resolve_conflicts(self): neighbours = self.nodes new_chain = None max_length = len(self.chain) for node in neighbours: response = requests.get(f'http://{node}/chain') if response.status_code == 200: length = response.json()['length'] chain = response.json()['chain'] if length > max_length and self.valid_chain(chain): max_length = length new_chain = chain if new_chain: self.chain = new_chain return True return False 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 if not self.valid_proof(last_block['proof'], block['proof']): return False last_block = block current_index += 1 return True app = Flask(__name__) blockchain = Blockchain() @app.route('/mine', methods=['POST']) def mine(): values = request.get_json() required = ['sender', 'recipient'] if not all(k in values for k in required): return 'Missing values', 400 last_block = blockchain.last_block last_proof = last_block['proof'] proof = blockchain.proof_of_work(last_proof) blockchain.new_transaction(sender=values['sender'], recipient=values['recipient'], amount=1) previous_hash = blockchain.hash(last_block) block = blockchain.new_block(proof, previous_hash) response = { 'message': 'New Block Forged', 'index': block['index'], 'block': block, } return jsonify(response), 200 @app.route('/transactions/new', methods=['POST']) def new_transaction(): values = request.get_json() required = ['sender', 'recipient', 'amount'] if not all(k in values for k in required): return 'Missing values', 400 index = blockchain.new_transaction(values['sender'], values['recipient'], values['amount']) response = {'message': f'Transaction will be added to Block {index}'} return jsonify(response), 201 @app.route('/chain', methods=['GET']) def full_chain(): response = { 'chain': blockchain.chain, 'length': len(blockchain.chain), } return jsonify(response), 200 @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 if __name__ == '__main__': app.run(debug=True)
Étape 2 : Améliorer le frontend
// src/components/Blockchain.vue <template> <div> <h1>Blockchain</h1> <button @click="fetchChain">Fetch Blockchain</button> <h2>Transactions</h2> <form @submit.prevent="submitTransaction"> <input type="text" v-model="sender" placeholder="Sender" required /> <input type="text" v-model="recipient" placeholder="Recipient" required /> <input type="number" v-model="amount" placeholder="Amount" required /> <button type="submit">Send Transaction</button> </form> <h2>Blockchain</h2> <ul> <li v-for="block in blockchain" :key="block.index"> Block #{{ block.index }} - {{ block.timestamp }} <ul> <li v-for="transaction in block.transactions" :key="transaction.sender"> {{ transaction.sender }} -> {{ transaction.recipient }}: {{ transaction.amount }} </li> </ul> </li> </ul> </div> </template> <script> import axios from 'axios'; export default { data() { return { blockchain: [], sender: '', recipient: '', amount: 0, }; }, methods: { fetchChain() { axios.get('http://localhost:5000/chain') .then(response => { this.blockchain = response.data.chain; }) .catch(error => { console.error(error); }); }, submitTransaction() { const transaction = { sender: this.sender, recipient: this.recipient, amount: this.amount, }; axios.post('http://localhost:5000/transactions/new', transaction) .then(response => { alert(response.data.message); this.fetchChain(); // Refresh the blockchain view }) .catch(error => { console.error(error); }); } } }; </script>
Vous pouvez tester votre blockchain avec plusieurs nœuds en exécutant plusieurs instances de votre application Flask sur différents ports. Par exemple, vous pouvez exécuter :
FLASK_RUN_PORT=5001 python blockchain.py
Ensuite, vous pouvez enregistrer des nœuds à l'aide d'une requête POST :
curl -X POST -H "Content-Type: application/json" -d '{"nodes": ["localhost:5001"]}' http://localhost:5000/nodes/register
Cette application blockchain plus avancée comprend :
-Preuve de travail : un mécanisme de base pour extraire de nouveaux blocs.
-Pool de transactions : les utilisateurs peuvent créer des transactions avant qu'elles ne soient extraites.
-Node Discovery : prise en charge de plusieurs nœuds et d'un mécanisme de consensus.
-Interactive Frontend : une interface utilisateur Vue.js pour soumettre des transactions et visualiser la blockchain.
Bon codage !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!