diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index a81f79a..31b9e1a 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -6,6 +6,7 @@ from flask import Flask, request from multiprocessing import Process, Pipe import ecdsa +import pprint from miner_config import MINER_ADDRESS, MINER_NODE_URL, PEER_NODES @@ -63,24 +64,29 @@ def create_genesis_block(): discarded and your transaction goes back as if it was never processed""" NODE_PENDING_TRANSACTIONS = [] - +start_time = time.time() def proof_of_work(last_proof, blockchain): # Creates a variable that we will use to find our next proof of work incrementer = last_proof + 1 # Keep incrementing the incrementer until it's equal to a number divisible by 7919 # and the proof of work of the previous block in the chain - start_time = time.time() + # start_time = time.time() + print(int((time.time()-start_time) % 60)) while not (incrementer % 7919 == 0 and incrementer % last_proof == 0): + # print('work') incrementer += 1 # Check if any node found the solution every 60 seconds if int((time.time()-start_time) % 60) == 0: + # print('check') + # If any other node got the proof, stop searching new_blockchain = consensus(blockchain) if new_blockchain: # (False: another node got proof first, new blockchain) return False, new_blockchain # Once that number is found, we can return it as a proof of our work + print(incrementer) return incrementer, blockchain @@ -143,7 +149,8 @@ def find_new_chains(): other_chains = [] for node_url in PEER_NODES: # Get their chains using a GET request - block = requests.get(url = node_url + "/blocks").content + block = requests.get(url=node_url + "/blocks").content + # print(block) # Convert the JSON object to a Python dictionary block = json.loads(block) # Verify other node block is correct @@ -191,9 +198,9 @@ def get_blocks(): chain_to_send_json = [] for block in chain_to_send: block = { - "index": str(block.index), - "timestamp": str(block.timestamp), - "data": str(block.data), + "index": block.index, + "timestamp": block.timestamp, + "data": block.data, "hash": block.hash } chain_to_send_json.append(block) @@ -203,6 +210,30 @@ def get_blocks(): return chain_to_send +@node.route('/balance', methods=['GET']) +def get_balance(): + address = request.args.get("address") + global BLOCKCHAIN + chain_to_send = BLOCKCHAIN + transaction_history = [] + c_counter = 0 + d_counter = 0 + for block in chain_to_send: + y = block.data + transaction_history.append(y["transactions"]) + for x in transaction_history: + if x is not None: + for y in x: + # print(y['to']) + if y['to'] == address: + c_counter = c_counter + y['amount'] + if y['from'] == address: + d_counter = d_counter + int(y['amount']) + + balance = c_counter - d_counter + return str(balance) + + @node.route('/txion', methods=['GET', 'POST']) def transaction(): """Each transaction sent to this node gets validated and submitted. @@ -247,7 +278,6 @@ def validate_signature(public_key, signature, message): except: return False - def welcome_msg(): print(""" =========================================\n SIMPLE COIN v1.0.0 - BLOCKCHAIN SYSTEM\n diff --git a/simpleCoin/miner_config.py b/simpleCoin/miner_config.py index b259c1b..b426f1f 100644 --- a/simpleCoin/miner_config.py +++ b/simpleCoin/miner_config.py @@ -3,7 +3,7 @@ """ # Write your generated adress here. All coins mined will go to this address -MINER_ADDRESS = "q3nf394hjg-random-miner-address-34nf3i4nflkn3oi" +MINER_ADDRESS = "e5yWZy7lcTm6ulr0rMmXxBGaYg4Mb10a+50SJb59MQm434y8bkRttCi5+SPWF4DxN3EIUEj2a2fLu9SVWRMe0g==" # Write your node url or ip. If you are running it localhost use default MINER_NODE_URL = "http://localhost:5000" @@ -11,3 +11,4 @@ # Store the url data of every other node in the network # so that we can communicate with them PEER_NODES = [] +# PEER_NODES = ['http://3.96.192.248:5000'] diff --git a/simpleCoin/test.py b/simpleCoin/test.py new file mode 100644 index 0000000..491fb31 --- /dev/null +++ b/simpleCoin/test.py @@ -0,0 +1,146 @@ +# Python Flask App to create Blockchain + +# For timestamp +import datetime + +# Calculating the hash +# in order to add digital +# fingerprints to the blocks +import hashlib + +# To store data +# in our blockchain +import json + +# Flask is for creating the web +# app and jsonify is for +# displaying the blockchain +from flask import Flask, jsonify + + +class Blockchain: + + # This function is created + # to create the very first + # block and set its hash to "0" + def __init__(self): + self.chain = [] + self.create_block(proof=1, previous_hash='0') + print(self.chain) + + # This function is created + # to add further blocks + # into the chain + def create_block(self, proof, previous_hash): + block = {'index': len(self.chain) + 1, + 'timestamp': str(datetime.datetime.now()), + 'proof': proof, + 'previous_hash': previous_hash} + self.chain.append(block) + return block + + # This function is created + # to display the previous block + def print_previous_block(self): + return self.chain[-1] + + # This is the function for proof of work + # and used to successfully mine the block + def proof_of_work(self, previous_proof): + new_proof = 1 + check_proof = False + + while check_proof is False: + hash_operation = hashlib.sha256( + str(new_proof ** 2 - previous_proof ** 2).encode()).hexdigest() + if hash_operation[:5] == '00000': + check_proof = True + else: + new_proof += 1 + + return new_proof + + def hash(self, block): + encoded_block = json.dumps(block, sort_keys=True).encode() + return hashlib.sha256(encoded_block).hexdigest() + + def chain_valid(self, chain): + previous_block = chain[0] + block_index = 1 + + while block_index < len(chain): + block = chain[block_index] + if block['previous_hash'] != self.hash(previous_block): + return False + + previous_proof = previous_block['proof'] + proof = block['proof'] + hash_operation = hashlib.sha256( + str(proof ** 2 - previous_proof ** 2).encode()).hexdigest() + + if hash_operation[:5] != '00000': + return False + previous_block = block + block_index += 1 + + return True + + +# Creating the Web +# App using flask +app = Flask(__name__) + +# Create the object +# of the class blockchain +blockchain = Blockchain() + + +# Mining a new block + + +@app.route('/mine_block', methods=['GET']) +def mine_block(): + print('mining') + previous_block = blockchain.print_previous_block() + previous_proof = previous_block['proof'] + proof = blockchain.proof_of_work(previous_proof) + previous_hash = blockchain.hash(previous_block) + block = blockchain.create_block(proof, previous_hash) + + response = {'message': 'A block is MINED', + 'index': block['index'], + 'timestamp': block['timestamp'], + 'proof': block['proof'], + 'previous_hash': block['previous_hash']} + + return jsonify(response), 200 + + +# Display blockchain in json format + + +@app.route('/get_chain', methods=['GET']) +def display_chain(): + response = {'chain': blockchain.chain, + 'length': len(blockchain.chain)} + return jsonify(response), 200 + + +# Check validity of blockchain + + +@app.route('/valid', methods=['GET']) +def valid(): + valid = blockchain.chain_valid(blockchain.chain) + + if valid: + response = {'message': 'The Blockchain is valid.'} + else: + response = {'message': 'The Blockchain is not valid.'} + return jsonify(response), 200 + + +# Run the flask server locally +app.run(host='127.0.0.1', port=5000) + +mine_block() \ No newline at end of file diff --git a/simpleCoin/wallet.py b/simpleCoin/wallet.py index f2f74f9..7c641dc 100644 --- a/simpleCoin/wallet.py +++ b/simpleCoin/wallet.py @@ -27,12 +27,13 @@ def wallet(): response = None - while response not in ["1", "2", "3", "4"]: + while response not in ["1", "2", "3", "4", "5"]: response = input("""What do you want to do? 1. Generate new wallet 2. Send coins to another wallet 3. Check transactions - 4. Quit\n""") + 4. Check Balance + 5. Quit\n""") if response == "1": # Generate new wallet print("""=========================================\n @@ -55,6 +56,9 @@ def wallet(): elif response == "3": # Will always occur when response == 3. check_transactions() return wallet() # return to main menu + elif response == "4": # Will always occur when response == 4. + check_balance() + return wallet() # return to main menu else: quit() @@ -100,6 +104,20 @@ def check_transactions(): print('Connection error. Make sure that you have run miner.py in another terminal.') +def check_balance(): + """Retrieve the entire blockchain. With this you can check your + wallets balance. If the blockchain is to long, it may take some time to load. + """ + try: + res = requests.get('http://localhost:5000/balance', params = + {'address':"rqH1SmqNBqnNojCin9fI4BdFHN/KsazIj/xasjZK6i1iFi03AApkKtQXzm61lUA6TMCvfbKg7+ylLkYvKZMfMg=="}) + # print(str(res)) + parsed = json.loads(res.text) + print('balance: ' + (json.dumps(parsed, indent=4, sort_keys=True))) + except requests.ConnectionError: + print('Connection error. Make sure that you have run miner.py in another terminal.') + + def generate_ECDSA_keys(): """This function takes care of creating your private and public (your address) keys. It's very important you don't lose any of them or those wallets will be lost