From 1c44c0ddf99c3013149c1abd23340d513bdca543 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Sun, 9 Sep 2018 12:35:31 -0400 Subject: [PATCH 01/56] initial upload. POW changed. networking issues identified. --- README.md | 2 + requirements.txt | 1 + simpleCoin/miner.py | 197 ++++++++++++++++++++++++++----------- simpleCoin/miner_config.py | 3 +- simpleCoin/user.py | 6 ++ simpleCoin/wallet.py | 1 + 6 files changed, 152 insertions(+), 58 deletions(-) create mode 100644 simpleCoin/user.py diff --git a/README.md b/README.md index c34ede6..1c04ae2 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,8 @@ When creating a wallet address, a new file will be generated with all your secur ## Contribution +Major code modifcations by HourGlss to change proof of work, memory usage, enable networking, and blockchain validation + Anybody is welcome to collaborate in this project. Feel free to push any pull request (even if you are new to coding). See ```CONTRIBUTING.md``` to learn how to contribute. Note: the idea of this project is to build a **really simple** blockchain system, so make sure all your code is easy to read (avoid too much code in 1 line) and don't introduce complex updates if they are not critical. In other words, keep it simple. diff --git a/requirements.txt b/requirements.txt index 16badde..89a4c04 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ Flask ecdsa requests +flask-sqlalchemy \ No newline at end of file diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 2e5b964..889a1f9 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -1,15 +1,34 @@ import time import hashlib +import sys import json import requests +import secrets +import string import base64 from flask import Flask, request from multiprocessing import Process, Pipe import ecdsa +import secrets +import string +import logging +import simpleCoin.user as user +try: + assert user.public_key != "" and user.private_key != "" +except AssertionError: + print("You need to generate keys in your wallet") + sys.exit() -from miner_config import MINER_ADDRESS, MINER_NODE_URL, PEER_NODES +from flask_sqlalchemy import SQLAlchemy + +log = logging.getLogger('werkzeug') +log.setLevel(logging.ERROR) + +from simpleCoin.miner_config import MINER_NODE_URL, PEER_NODES node = Flask(__name__) +node.config['SQLALCHEMY_DATABASE_URI'] = "" +node.config['SECRET_KEY'] = user.secret_key class Block: @@ -48,10 +67,17 @@ def create_genesis_block(): """To create each block, it needs the hash of the previous one. First block has no previous, so it must be created manually (with index zero and arbitrary previous hash)""" - return Block(0, time.time(), { - "proof-of-work": 9, + b = Block(0, time.time(), { + "proof-of-work": "00000001337deadbeef1337deadbeef1337deadbeef1337deadbeef1337deadb", "transactions": None}, - "0") + "0") + print(json.dumps({ + "index": b.index, + "timestamp": str(b.timestamp), + "data": b.data, + "hash": b.hash + }) + "\n") + return b # Node's blockchain copy @@ -66,22 +92,41 @@ def create_genesis_block(): 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 9 - # and the proof of work of the previous block in the chain + def random_str(): + # Generate a random size string from 3 - 27 characters long + rand_str = '' + for i in range(0, 3 + secrets.randbelow(25)): + rand_str += string.ascii_lowercase[secrets.randbelow(26)] # each char is a random downcase letter [a-z] + return rand_str + + def genhash(): + # Generate random string + r = random_str() + # Create hash object + m = hashlib.sha3_256() + # update that hash object with the string + m.update(r.encode("utf-8")) + + # return the string format of the hash + return m.hexdigest() + + pow_hash = genhash() start_time = time.time() - while not (incrementer % 7919 == 0 and incrementer % last_proof == 0): - incrementer += 1 + # check to see if the first characters of the string are 0 + work = 4 + while not (pow_hash[0:work] == ("0" * work)): + # Check if any node found the solution every 60 seconds - if int((time.time()-start_time) % 60) == 0: + if int((time.time() - start_time) % 60) == 0: # If any other node got the proof, stop searching - new_blockchain = consensus(blockchain) + new_blockchain = consensus() 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 - return incrementer, blockchain + # generate new hash for next time + pow_hash = genhash() + # Once that hash is found, we can return it as a proof of our work + return pow_hash, blockchain def mine(a, blockchain, node_pending_transactions): @@ -108,12 +153,12 @@ def mine(a, blockchain, node_pending_transactions): # Once we find a valid proof of work, we know we can mine a block so # ...we reward the miner by adding a transaction # First we load all pending transactions sent to the node server - NODE_PENDING_TRANSACTIONS = requests.get(MINER_NODE_URL + "/txion?update=" + MINER_ADDRESS).content + NODE_PENDING_TRANSACTIONS = requests.get(MINER_NODE_URL + "/txion?update=" + user.public_key).content NODE_PENDING_TRANSACTIONS = json.loads(NODE_PENDING_TRANSACTIONS) # Then we add the mining reward NODE_PENDING_TRANSACTIONS.append({ "from": "network", - "to": MINER_ADDRESS, + "to": user.public_key, "amount": 1}) # Now we can gather the data needed to create the new block new_block_data = { @@ -130,13 +175,13 @@ def mine(a, blockchain, node_pending_transactions): BLOCKCHAIN.append(mined_block) # Let the client know this node mined a block print(json.dumps({ - "index": new_block_index, - "timestamp": str(new_block_timestamp), - "data": new_block_data, - "hash": last_block_hash + "index": new_block_index, + "timestamp": str(new_block_timestamp), + "data": new_block_data, + "hash": last_block_hash }) + "\n") a.send(BLOCKCHAIN) - requests.get(MINER_NODE_URL + "/blocks?update=" + MINER_ADDRESS) + requests.get(MINER_NODE_URL + "/blocks?update=" + user.public_key) def find_new_chains(): @@ -144,22 +189,27 @@ def find_new_chains(): other_chains = [] for node_url in PEER_NODES: # Get their chains using a GET request - block = requests.get(node_url + "/blocks").content + blocks = None + try: + blocks = requests.get(node_url + "/blocks").content + except: + pass # Convert the JSON object to a Python dictionary - block = json.loads(block) - # Verify other node block is correct - validated = validate_blockchain(block) - if validated: - # Add it to our list - other_chains.append(block) + if blocks is not None: + blocks = json.loads(blocks) + # Verify other node block is correct + validated = validate_blockchain(blocks) + if validated: + # Add it to our list + other_chains.append(blocks) return other_chains -def consensus(blockchain): +def consensus(): # Get the blocks from other nodes other_chains = find_new_chains() # If our chain isn't longest, then we store the longest chain - BLOCKCHAIN = blockchain + global BLOCKCHAIN longest_chain = BLOCKCHAIN for chain in other_chains: if len(longest_chain) < len(chain): @@ -181,10 +231,34 @@ def validate_blockchain(block): return True +def validate_signature(public_key, signature, message): + """Verifies if the signature is correct. This is used to prove + it's you (and not someone else) trying to do a transaction with your + address. Called when a user tries to submit a new transaction. + """ + public_key = (base64.b64decode(public_key)).hex() + signature = base64.b64decode(signature) + vk = ecdsa.VerifyingKey.from_string(bytes.fromhex(public_key), curve=ecdsa.SECP256k1) + # Try changing into an if/else statement as except is too broad. + try: + return vk.verify(signature, message.encode()) + except: + return False + + +def welcome_msg(): + print(""" =========================================\n + SIMPLE COIN v1.0.0 - BLOCKCHAIN SYSTEM\n + =========================================\n\n + You can find more help at: https://github.com/cosme12/SimpleCoin\n + Make sure you are using the latest version or you may end in + a parallel chain.\n\n\n""") + + @node.route('/blocks', methods=['GET']) def get_blocks(): # Load current blockchain. Only you should update your blockchain - if request.args.get("update") == MINER_ADDRESS: + if request.args.get("update") == user.public_key: global BLOCKCHAIN BLOCKCHAIN = b.recv() chain_to_send = BLOCKCHAIN @@ -207,8 +281,7 @@ def get_blocks(): @node.route('/txion', methods=['GET', 'POST']) def transaction(): """Each transaction sent to this node gets validated and submitted. - Then it waits to be added to the blockchain. Transactions only move - coins, they don't create it. + Then it waits to be added to the blockchain. Transactions only move coins, they don't create it. """ if request.method == 'POST': # On each new POST request, we extract the transaction data @@ -227,43 +300,55 @@ def transaction(): else: return "Transaction submission failed. Wrong signature\n" # Send pending transactions to the mining process - elif request.method == 'GET' and request.args.get("update") == MINER_ADDRESS: + elif request.method == 'GET' and request.args.get("update") == user.public_key: pending = json.dumps(NODE_PENDING_TRANSACTIONS) # Empty transaction list NODE_PENDING_TRANSACTIONS[:] = [] return pending -def validate_signature(public_key, signature, message): - """Verifies if the signature is correct. This is used to prove - it's you (and not someone else) trying to do a transaction with your - address. Called when a user tries to submit a new transaction. - """ - public_key = (base64.b64decode(public_key)).hex() - signature = base64.b64decode(signature) - vk = ecdsa.VerifyingKey.from_string(bytes.fromhex(public_key), curve=ecdsa.SECP256k1) - # Try changing into an if/else statement as except is too broad. - try: - return vk.verify(signature, message.encode()) - except: - return False - +@node.route('/balances', methods=['GET']) +def get_balance(): + global BLOCKCHAIN + working = BLOCKCHAIN + balances = {} + balances_json = [] + + for block in working: + if block.data['transactions'] is not None: + for transaction in block.data['transactions']: + to = transaction['to'] + source = transaction['from'] + amount = transaction['amount'] + + if type(amount) == type("string"): + amount = eval(amount) + + if to in balances: + balances[to] += amount + else: + balances[to] = amount + if source != "network": + balances[source] -= amount + + for k, v in balances.items(): + account = { + "address": str(k), + "amount": str(v) + } + balances_json.append(account) -def welcome_msg(): - print(""" =========================================\n - SIMPLE COIN v1.0.0 - BLOCKCHAIN SYSTEM\n - =========================================\n\n - You can find more help at: https://github.com/cosme12/SimpleCoin\n - Make sure you are using the latest version or you may end in - a parallel chain.\n\n\n""") + return json.dumps(balances_json) if __name__ == '__main__': + welcome_msg() # Start mining a, b = Pipe() + print(b) p1 = Process(target=mine, args=(a, BLOCKCHAIN, NODE_PENDING_TRANSACTIONS)) p1.start() # Start server to receive transactions - p2 = Process(target=node.run(), args=b) + p2 = Process(target=node.run(host="0.0.0.0", port=5000), args=b) p2.start() diff --git a/simpleCoin/miner_config.py b/simpleCoin/miner_config.py index b259c1b..a9e19eb 100644 --- a/simpleCoin/miner_config.py +++ b/simpleCoin/miner_config.py @@ -1,9 +1,8 @@ """Configure this file before you start mining. Check wallet.py for more details. """ - +import simpleCoin.user # Write your generated adress here. All coins mined will go to this address -MINER_ADDRESS = "q3nf394hjg-random-miner-address-34nf3i4nflkn3oi" # Write your node url or ip. If you are running it localhost use default MINER_NODE_URL = "http://localhost:5000" diff --git a/simpleCoin/user.py b/simpleCoin/user.py new file mode 100644 index 0000000..63f284a --- /dev/null +++ b/simpleCoin/user.py @@ -0,0 +1,6 @@ +import hashlib +m = hashlib.sha3_256() +m.update("This is your password now!".encode('utf-8')) +secret_key = "" +private_key = "" +public_key = "" \ No newline at end of file diff --git a/simpleCoin/wallet.py b/simpleCoin/wallet.py index 8f3aec7..545c947 100644 --- a/simpleCoin/wallet.py +++ b/simpleCoin/wallet.py @@ -46,6 +46,7 @@ def wallet(): print("Is everything correct?\n") print("From: {0}\nPrivate Key: {1}\nTo: {2}\nAmount: {3}\n".format(addr_from, private_key, addr_to, amount)) response = input("y/n\n") + print("From: {0}\nPrivate Key: {1}\nTo: {2}\nAmount: {3}\n".format(addr_from, private_key, addr_to, amount)) if response.lower() == "y": send_transaction(addr_from, private_key, addr_to, amount) else: # Will always occur when response == 3. From d1eb99421ac2a38f2257b0cec21f2cf189cdcdb1 Mon Sep 17 00:00:00 2001 From: Horological Date: Sun, 9 Sep 2018 23:29:16 -0400 Subject: [PATCH 02/56] fixed verifiability and some security issues without making things complex. --- .gitignore | 4 +- simpleCoin/miner.py | 101 +++++++++++++++++++++++++------------------- simpleCoin/user.py | 6 +-- 3 files changed, 63 insertions(+), 48 deletions(-) diff --git a/.gitignore b/.gitignore index 7e99e36..e0fa44c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -*.pyc \ No newline at end of file +*.pyc +scratch.py +xyf.txt diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 889a1f9..a5d47e0 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -13,6 +13,7 @@ import string import logging import simpleCoin.user as user + try: assert user.public_key != "" and user.private_key != "" except AssertionError: @@ -39,13 +40,13 @@ def __init__(self, index, timestamp, data, previous_hash): Args: index (int): Block number. timestamp (int): Block creation timestamp. - data (str): Data to be sent. + data (dict): Data to be sent. previous_hash(str): String representing previous block unique hash. Attrib: index (int): Block number. timestamp (int): Block creation timestamp. - data (str): Data to be sent. + data (dict): Data to be sent. previous_hash(str): String representing previous block unique hash. hash(str): Current block unique hash. @@ -53,6 +54,12 @@ def __init__(self, index, timestamp, data, previous_hash): self.index = index self.timestamp = timestamp self.data = data + ''' + data contains: + proof-of-work (str) + transations: (list?) + + ''' self.previous_hash = previous_hash self.hash = self.hash_block() @@ -62,21 +69,26 @@ def hash_block(self): sha.update((str(self.index) + str(self.timestamp) + str(self.data) + str(self.previous_hash)).encode('utf-8')) return sha.hexdigest() + def __repr__(self): + return str(self) + def __str__(self): + return "i: {} time: {} data: {} previous: {} hash: {}".format(self.index, self.timestamp, self.data, self.previous_hash, self.hash) + def create_genesis_block(): """To create each block, it needs the hash of the previous one. First block has no previous, so it must be created manually (with index zero and arbitrary previous hash)""" b = Block(0, time.time(), { - "proof-of-work": "00000001337deadbeef1337deadbeef1337deadbeef1337deadbeef1337deadb", + "proof-of-work": "1337", "transactions": None}, "0") - print(json.dumps({ - "index": b.index, - "timestamp": str(b.timestamp), - "data": b.data, - "hash": b.hash - }) + "\n") + # print(json.dumps({ + # "index": b.index, + # "timestamp": str(b.timestamp), + # "data": b.data, + # "hash": b.hash + # }) + "\n") return b @@ -91,29 +103,29 @@ def create_genesis_block(): NODE_PENDING_TRANSACTIONS = [] -def proof_of_work(last_proof, blockchain): +def proof_of_work(last_block,transactions): + + data = {"transactions":transactions} + pow = "" def random_str(): # Generate a random size string from 3 - 27 characters long rand_str = '' - for i in range(0, 3 + secrets.randbelow(25)): + for i in range(0, 0 + secrets.randbelow(25)): rand_str += string.ascii_lowercase[secrets.randbelow(26)] # each char is a random downcase letter [a-z] return rand_str def genhash(): - # Generate random string - r = random_str() - # Create hash object + pow = random_str() m = hashlib.sha3_256() - # update that hash object with the string - m.update(r.encode("utf-8")) + data["proof-of-work"] = pow + m.update((str(last_block.index) + str(last_block.timestamp) + str(data) + str(last_block.previous_hash)).encode('utf-8')) - # return the string format of the hash - return m.hexdigest() + return pow,m.hexdigest() - pow_hash = genhash() + pow,pow_hash = genhash() start_time = time.time() # check to see if the first characters of the string are 0 - work = 4 + work = 1 while not (pow_hash[0:work] == ("0" * work)): # Check if any node found the solution every 60 seconds @@ -126,11 +138,11 @@ def genhash(): # generate new hash for next time pow_hash = genhash() # Once that hash is found, we can return it as a proof of our work - return pow_hash, blockchain + return pow,pow_hash def mine(a, blockchain, node_pending_transactions): - BLOCKCHAIN = blockchain + global BLOCKCHAIN NODE_PENDING_TRANSACTIONS = node_pending_transactions while True: """Mining is the only way that new coins can be created. @@ -139,10 +151,19 @@ def mine(a, blockchain, node_pending_transactions): """ # Get the last proof of work last_block = BLOCKCHAIN[len(BLOCKCHAIN) - 1] - last_proof = last_block.data['proof-of-work'] + NODE_PENDING_TRANSACTIONS = requests.get(MINER_NODE_URL + "/txion?update=" + user.public_key).content + NODE_PENDING_TRANSACTIONS = json.loads(NODE_PENDING_TRANSACTIONS) + # Then we add the mining reward + NODE_PENDING_TRANSACTIONS.append({ + "from": "network", + "to": user.public_key, + "amount": 1.0}) + + # Find the proof of work for the current block being mined # Note: The program will hang here until a new proof of work is found - proof = proof_of_work(last_proof, BLOCKCHAIN) + + proof = proof_of_work(last_block, NODE_PENDING_TRANSACTIONS) # If we didn't guess the proof, start mining again if not proof[0]: # Update blockchain and save it to file @@ -150,16 +171,7 @@ def mine(a, blockchain, node_pending_transactions): a.send(BLOCKCHAIN) continue else: - # Once we find a valid proof of work, we know we can mine a block so - # ...we reward the miner by adding a transaction - # First we load all pending transactions sent to the node server - NODE_PENDING_TRANSACTIONS = requests.get(MINER_NODE_URL + "/txion?update=" + user.public_key).content - NODE_PENDING_TRANSACTIONS = json.loads(NODE_PENDING_TRANSACTIONS) - # Then we add the mining reward - NODE_PENDING_TRANSACTIONS.append({ - "from": "network", - "to": user.public_key, - "amount": 1}) + # Now we can gather the data needed to create the new block new_block_data = { "proof-of-work": proof[0], @@ -167,19 +179,22 @@ def mine(a, blockchain, node_pending_transactions): } new_block_index = last_block.index + 1 new_block_timestamp = time.time() - last_block_hash = last_block.hash + # Empty transaction list NODE_PENDING_TRANSACTIONS = [] # Now create the new block - mined_block = Block(new_block_index, new_block_timestamp, new_block_data, last_block_hash) + mined_block = Block(new_block_index, new_block_timestamp, new_block_data, last_block.hash) + for block in BLOCKCHAIN: + print(block) + BLOCKCHAIN.append(mined_block) # Let the client know this node mined a block - print(json.dumps({ - "index": new_block_index, - "timestamp": str(new_block_timestamp), - "data": new_block_data, - "hash": last_block_hash - }) + "\n") + # print(json.dumps({ + # "index": new_block_index, + # "timestamp": str(new_block_timestamp), + # "data": new_block_data, + # "hash": last_block_hash + # }) + "\n") a.send(BLOCKCHAIN) requests.get(MINER_NODE_URL + "/blocks?update=" + user.public_key) @@ -342,11 +357,9 @@ def get_balance(): if __name__ == '__main__': - welcome_msg() # Start mining a, b = Pipe() - print(b) p1 = Process(target=mine, args=(a, BLOCKCHAIN, NODE_PENDING_TRANSACTIONS)) p1.start() # Start server to receive transactions diff --git a/simpleCoin/user.py b/simpleCoin/user.py index 63f284a..b25b038 100644 --- a/simpleCoin/user.py +++ b/simpleCoin/user.py @@ -1,6 +1,6 @@ import hashlib m = hashlib.sha3_256() m.update("This is your password now!".encode('utf-8')) -secret_key = "" -private_key = "" -public_key = "" \ No newline at end of file +secret_key = m.hexdigest() +private_key = "b87cfd49cfe5d3d0ef64094f97e40435cd0e0087661ea97a0679b97f7f2e0fc7" +public_key = "9ZTW4v76LnVTZUQu9mZrFru/0IEAc6xQJqb/OpSYFQ90eQvpbUZmn140WhvlidWrMsWA2jTaz8cKEtSX0nlTmw==" \ No newline at end of file From 3827e0b4d478d795f6d7f0f91e9d93146b4810a5 Mon Sep 17 00:00:00 2001 From: Horological Date: Tue, 11 Sep 2018 03:13:13 -0400 Subject: [PATCH 03/56] blockchain validation works --- simpleCoin/Block.py | 53 ++++++++++++++++++++++++ simpleCoin/miner.py | 99 +++++++++++++++++---------------------------- 2 files changed, 91 insertions(+), 61 deletions(-) create mode 100644 simpleCoin/Block.py diff --git a/simpleCoin/Block.py b/simpleCoin/Block.py new file mode 100644 index 0000000..bb1e53d --- /dev/null +++ b/simpleCoin/Block.py @@ -0,0 +1,53 @@ +import hashlib +class Block: + def __init__(self, index, timestamp, data, previous_hash): + """Returns a new Block object. Each block is "chained" to its previous + by calling its unique hash. + + Args: + index (int): Block number. + timestamp (int): Block creation timestamp. + data (dict): Data to be sent. + previous_hash(str): String representing previous block unique hash. + + Attrib: + index (int): Block number. + timestamp (int): Block creation timestamp. + data (dict): Data to be sent. + previous_hash(str): String representing previous block unique hash. + hash(str): Current block unique hash. + + """ + self.index = index + self.timestamp = timestamp + self.data = data + ''' + data contains: + proof-of-work (str) + transations: (list?) + + ''' + self.previous_hash = previous_hash + self.hash = self.hash_block() + + def hash_block(self): + """Creates the unique hash for the block. It uses sha256.""" + sha = hashlib.sha256() + sha.update((str(self.index) + str(self.timestamp) + str(self.data) + str(self.previous_hash)).encode('utf-8')) + return sha.hexdigest() + + def validate(self,effort): + ''' + + :param effort: number of digits of zero in proof of work + :return: True or False if this block is valid + ''' + if self.data['proof-of-work'][0:effort] != "0"*effort: + return False + return True + + def __repr__(self): + return "Block({},{},{},\"{}\")".format(self.index,self.timestamp,self.data,self.previous_hash,self.hash) + + def __str__(self): + return "i: {} time: {} data: {} previous: {} hash: {}".format(self.index, self.timestamp, self.data, self.previous_hash, self.hash) \ No newline at end of file diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index a5d47e0..571225e 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -13,6 +13,7 @@ import string import logging import simpleCoin.user as user +from simpleCoin.Block import Block try: assert user.public_key != "" and user.private_key != "" @@ -31,56 +32,20 @@ node.config['SQLALCHEMY_DATABASE_URI'] = "" node.config['SECRET_KEY'] = user.secret_key - -class Block: - def __init__(self, index, timestamp, data, previous_hash): - """Returns a new Block object. Each block is "chained" to its previous - by calling its unique hash. - - Args: - index (int): Block number. - timestamp (int): Block creation timestamp. - data (dict): Data to be sent. - previous_hash(str): String representing previous block unique hash. - - Attrib: - index (int): Block number. - timestamp (int): Block creation timestamp. - data (dict): Data to be sent. - previous_hash(str): String representing previous block unique hash. - hash(str): Current block unique hash. - - """ - self.index = index - self.timestamp = timestamp - self.data = data - ''' - data contains: - proof-of-work (str) - transations: (list?) - - ''' - self.previous_hash = previous_hash - self.hash = self.hash_block() - - def hash_block(self): - """Creates the unique hash for the block. It uses sha256.""" - sha = hashlib.sha256() - sha.update((str(self.index) + str(self.timestamp) + str(self.data) + str(self.previous_hash)).encode('utf-8')) - return sha.hexdigest() - - def __repr__(self): - return str(self) - def __str__(self): - return "i: {} time: {} data: {} previous: {} hash: {}".format(self.index, self.timestamp, self.data, self.previous_hash, self.hash) +work = 2 def create_genesis_block(): """To create each block, it needs the hash of the previous one. First block has no previous, so it must be created manually (with index zero and arbitrary previous hash)""" + global work + pow = "0" * work + pad = "1337" + for i in range(4, 64): + pow += pad[i % work] b = Block(0, time.time(), { - "proof-of-work": "1337", + "proof-of-work": pow, "transactions": None}, "0") # print(json.dumps({ @@ -94,7 +59,7 @@ def create_genesis_block(): # Node's blockchain copy BLOCKCHAIN = [create_genesis_block()] - +print("b{}=".format(BLOCKCHAIN[0].index),repr(BLOCKCHAIN[0])) """ Stores the transactions that this node has in a list. If the node you sent the transaction adds a block it will get accepted, but there is a chance it gets @@ -103,10 +68,10 @@ def create_genesis_block(): NODE_PENDING_TRANSACTIONS = [] -def proof_of_work(last_block,transactions): - - data = {"transactions":transactions} +def proof_of_work(last_block, transactions): + data = {"transactions": list(transactions)} pow = "" + def random_str(): # Generate a random size string from 3 - 27 characters long rand_str = '' @@ -119,13 +84,12 @@ def genhash(): m = hashlib.sha3_256() data["proof-of-work"] = pow m.update((str(last_block.index) + str(last_block.timestamp) + str(data) + str(last_block.previous_hash)).encode('utf-8')) + return pow, m.hexdigest() - return pow,m.hexdigest() - - pow,pow_hash = genhash() + pow, pow_hash = genhash() start_time = time.time() # check to see if the first characters of the string are 0 - work = 1 + global work while not (pow_hash[0:work] == ("0" * work)): # Check if any node found the solution every 60 seconds @@ -136,9 +100,9 @@ def genhash(): # (False: another node got proof first, new blockchain) return False, new_blockchain # generate new hash for next time - pow_hash = genhash() + pow, pow_hash = genhash() # Once that hash is found, we can return it as a proof of our work - return pow,pow_hash + return pow, pow_hash def mine(a, blockchain, node_pending_transactions): @@ -159,7 +123,6 @@ def mine(a, blockchain, node_pending_transactions): "to": user.public_key, "amount": 1.0}) - # Find the proof of work for the current block being mined # Note: The program will hang here until a new proof of work is found @@ -174,7 +137,7 @@ def mine(a, blockchain, node_pending_transactions): # Now we can gather the data needed to create the new block new_block_data = { - "proof-of-work": proof[0], + "proof-of-work": proof[1], "transactions": list(NODE_PENDING_TRANSACTIONS) } new_block_index = last_block.index + 1 @@ -184,8 +147,7 @@ def mine(a, blockchain, node_pending_transactions): NODE_PENDING_TRANSACTIONS = [] # Now create the new block mined_block = Block(new_block_index, new_block_timestamp, new_block_data, last_block.hash) - for block in BLOCKCHAIN: - print(block) + print("b{}=".format(mined_block.index),repr(mined_block)) BLOCKCHAIN.append(mined_block) # Let the client know this node mined a block @@ -239,10 +201,25 @@ def consensus(): return BLOCKCHAIN -def validate_blockchain(block): - """Validate the submitted chain. If hashes are not correct, return false - block(str): json - """ +def validate_blockchain(blockchain): + global work + + previous = "" + for block in blockchain: + if not block.validate(work): + return False + if block.index == 0: + previous = block.hash + continue + else: + sha = hashlib.sha256() + sha.update((str(block.index) + str(block.timestamp) + str(block.data) + str(block.previous_hash)).encode('utf-8')) + if sha.hexdigest() != block.hash: + return False + if previous != block.previous_hash: + return False + previous = block.hash + return True From afe3f4bbd206093b819245fabdd2e4a4c75d85de Mon Sep 17 00:00:00 2001 From: Horological Date: Tue, 11 Sep 2018 03:37:33 -0400 Subject: [PATCH 04/56] improved networking so that if someone downloads out chains, we add them to the network --- simpleCoin/miner.py | 11 +++++++++-- simpleCoin/miner_config.py | 9 +++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 571225e..e4daf67 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -14,6 +14,7 @@ import logging import simpleCoin.user as user from simpleCoin.Block import Block +from simpleCoin.miner_config import MINER_NODE_URL, PEER_NODES, PORT try: assert user.public_key != "" and user.private_key != "" @@ -26,7 +27,7 @@ log = logging.getLogger('werkzeug') log.setLevel(logging.ERROR) -from simpleCoin.miner_config import MINER_NODE_URL, PEER_NODES + node = Flask(__name__) node.config['SQLALCHEMY_DATABASE_URI'] = "" @@ -189,6 +190,8 @@ def consensus(): global BLOCKCHAIN longest_chain = BLOCKCHAIN for chain in other_chains: + if longest_chain == BLOCKCHAIN: + continue if len(longest_chain) < len(chain): longest_chain = chain # If the longest chain wasn't ours, then we set our chain to the longest @@ -266,6 +269,9 @@ def get_blocks(): chain_to_send_json.append(block) # Send our chain to whomever requested it + ip = request.remote_addr+":"+PORT + if ip not in PEER_NODES: + PEER_NODES.append(ip) chain_to_send = json.dumps(chain_to_send_json) return chain_to_send @@ -275,6 +281,7 @@ def transaction(): """Each transaction sent to this node gets validated and submitted. Then it waits to be added to the blockchain. Transactions only move coins, they don't create it. """ + if request.method == 'POST': # On each new POST request, we extract the transaction data new_txion = request.get_json() @@ -340,5 +347,5 @@ def get_balance(): p1 = Process(target=mine, args=(a, BLOCKCHAIN, NODE_PENDING_TRANSACTIONS)) p1.start() # Start server to receive transactions - p2 = Process(target=node.run(host="0.0.0.0", port=5000), args=b) + p2 = Process(target=node.run(host="0.0.0.0", port=PORT), args=b) p2.start() diff --git a/simpleCoin/miner_config.py b/simpleCoin/miner_config.py index a9e19eb..dd431c7 100644 --- a/simpleCoin/miner_config.py +++ b/simpleCoin/miner_config.py @@ -1,11 +1,8 @@ -"""Configure this file before you start mining. Check wallet.py for -more details. -""" import simpleCoin.user -# Write your generated adress here. All coins mined will go to this address - +# Port to run on +PORT = 5000 # Write your node url or ip. If you are running it localhost use default -MINER_NODE_URL = "http://localhost:5000" +MINER_NODE_URL = "http://localhost:"+str(PORT) # Store the url data of every other node in the network # so that we can communicate with them From 4ca5f7cfd4a4582b02f6c37fe6e668f2fbd1dba4 Mon Sep 17 00:00:00 2001 From: Horological Date: Tue, 11 Sep 2018 04:00:20 -0400 Subject: [PATCH 05/56] Transactions should now propagate through network. this is untested still. --- simpleCoin/miner.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index e4daf67..6ce9472 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -116,7 +116,7 @@ def mine(a, blockchain, node_pending_transactions): """ # Get the last proof of work last_block = BLOCKCHAIN[len(BLOCKCHAIN) - 1] - NODE_PENDING_TRANSACTIONS = requests.get(MINER_NODE_URL + "/txion?update=" + user.public_key).content + NODE_PENDING_TRANSACTIONS = requests.get(MINER_NODE_URL + ":"+PORT+"/txion?update=" + user.public_key).content NODE_PENDING_TRANSACTIONS = json.loads(NODE_PENDING_TRANSACTIONS) # Then we add the mining reward NODE_PENDING_TRANSACTIONS.append({ @@ -159,7 +159,7 @@ def mine(a, blockchain, node_pending_transactions): # "hash": last_block_hash # }) + "\n") a.send(BLOCKCHAIN) - requests.get(MINER_NODE_URL + "/blocks?update=" + user.public_key) + requests.get(MINER_NODE_URL + ":"+PORT+"/blocks?update=" + user.public_key) def find_new_chains(): @@ -169,7 +169,7 @@ def find_new_chains(): # Get their chains using a GET request blocks = None try: - blocks = requests.get(node_url + "/blocks").content + blocks = requests.get(node_url+":"+PORT + "/blocks").content except: pass # Convert the JSON object to a Python dictionary @@ -270,7 +270,7 @@ def get_blocks(): # Send our chain to whomever requested it ip = request.remote_addr+":"+PORT - if ip not in PEER_NODES: + if str(ip) != "127.0.0.1" and ip not in PEER_NODES: PEER_NODES.append(ip) chain_to_send = json.dumps(chain_to_send_json) return chain_to_send @@ -279,7 +279,7 @@ def get_blocks(): @node.route('/txion', methods=['GET', 'POST']) def transaction(): """Each transaction sent to this node gets validated and submitted. - Then it waits to be added to the blockchain. Transactions only move coins, they don't create it. + Then it waits to be added to the blockchain. Transactions only move coins, they don't create it. """ if request.method == 'POST': @@ -295,6 +295,15 @@ def transaction(): print("TO: {0}".format(new_txion['to'])) print("AMOUNT: {0}\n".format(new_txion['amount'])) # Then we let the client know it worked out + + #Push to all other available nodes + for node_url in PEER_NODES: + if node_url != request.remote_addr: + try: + headers = {"Content-Type": "application/json"} + requests.post(node_url+":"+PORT+"/txion",json = new_txion,headers = headers) + except: + pass return "Transaction submission successful\n" else: return "Transaction submission failed. Wrong signature\n" From b6fc334a3aeb81c70ee0fe0ce01e156ede2a2082 Mon Sep 17 00:00:00 2001 From: Horological Date: Tue, 11 Sep 2018 04:07:04 -0400 Subject: [PATCH 06/56] removed printing --- .gitignore | 2 +- simpleCoin/miner.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index e0fa44c..a80e949 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ *.pyc -scratch.py +*scratch.py xyf.txt diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 6ce9472..96fe99c 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -60,7 +60,6 @@ def create_genesis_block(): # Node's blockchain copy BLOCKCHAIN = [create_genesis_block()] -print("b{}=".format(BLOCKCHAIN[0].index),repr(BLOCKCHAIN[0])) """ Stores the transactions that this node has in a list. If the node you sent the transaction adds a block it will get accepted, but there is a chance it gets @@ -148,7 +147,6 @@ def mine(a, blockchain, node_pending_transactions): NODE_PENDING_TRANSACTIONS = [] # Now create the new block mined_block = Block(new_block_index, new_block_timestamp, new_block_data, last_block.hash) - print("b{}=".format(mined_block.index),repr(mined_block)) BLOCKCHAIN.append(mined_block) # Let the client know this node mined a block From 5f94e08dc6638f88e16cf4a8cabc17f79100dfe0 Mon Sep 17 00:00:00 2001 From: Horological Date: Tue, 11 Sep 2018 04:10:27 -0400 Subject: [PATCH 07/56] updated validation --- .gitignore | 2 +- simpleCoin/Block.py | 2 +- simpleCoin/miner.py | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index a80e949..e3320ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ *.pyc -*scratch.py +simpleCoin/scratch.py xyf.txt diff --git a/simpleCoin/Block.py b/simpleCoin/Block.py index bb1e53d..4da8e17 100644 --- a/simpleCoin/Block.py +++ b/simpleCoin/Block.py @@ -24,7 +24,7 @@ def __init__(self, index, timestamp, data, previous_hash): ''' data contains: proof-of-work (str) - transations: (list?) + transactions: (list?) ''' self.previous_hash = previous_hash diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 96fe99c..8469a9c 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -16,6 +16,7 @@ from simpleCoin.Block import Block from simpleCoin.miner_config import MINER_NODE_URL, PEER_NODES, PORT + try: assert user.public_key != "" and user.private_key != "" except AssertionError: @@ -209,6 +210,9 @@ def validate_blockchain(blockchain): for block in blockchain: if not block.validate(work): return False + for transaction in block.data['transactions']: + if transaction['from'] == "network" and transaction['amount'] != 1: + return False if block.index == 0: previous = block.hash continue From 02a8b19f73b4be3b45cc9e5eb3c8c96f0dc60aa7 Mon Sep 17 00:00:00 2001 From: Horological Date: Tue, 11 Sep 2018 06:24:04 -0400 Subject: [PATCH 08/56] updated pow / effort so that it's more controllable --- simpleCoin/miner.py | 50 +++++++++++++++++++++++++++----------- simpleCoin/miner_config.py | 2 +- simpleCoin/scratch.py | 39 +++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 15 deletions(-) create mode 100644 simpleCoin/scratch.py diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 8469a9c..502403d 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -34,18 +34,21 @@ node.config['SQLALCHEMY_DATABASE_URI'] = "" node.config['SECRET_KEY'] = user.secret_key -work = 2 - - +work = 21 +try: + assert work > 0 and work < 65 +except AssertionError: + print("Work value must be greater than 0 and less than 65") def create_genesis_block(): """To create each block, it needs the hash of the previous one. First block has no previous, so it must be created manually (with index zero and arbitrary previous hash)""" global work - pow = "0" * work + work_ez = int(work / 4) + 1 + pow = "0" * work_ez pad = "1337" for i in range(4, 64): - pow += pad[i % work] + pow += pad[i % len(pad)] b = Block(0, time.time(), { "proof-of-work": pow, "transactions": None}, @@ -61,6 +64,7 @@ def create_genesis_block(): # Node's blockchain copy BLOCKCHAIN = [create_genesis_block()] +print(BLOCKCHAIN[0]) """ Stores the transactions that this node has in a list. If the node you sent the transaction adds a block it will get accepted, but there is a chance it gets @@ -76,7 +80,7 @@ def proof_of_work(last_block, transactions): def random_str(): # Generate a random size string from 3 - 27 characters long rand_str = '' - for i in range(0, 0 + secrets.randbelow(25)): + for i in range(0, 1 + secrets.randbelow(25)): rand_str += string.ascii_lowercase[secrets.randbelow(26)] # each char is a random downcase letter [a-z] return rand_str @@ -85,13 +89,25 @@ def genhash(): m = hashlib.sha3_256() data["proof-of-work"] = pow m.update((str(last_block.index) + str(last_block.timestamp) + str(data) + str(last_block.previous_hash)).encode('utf-8')) - return pow, m.hexdigest() + + return pow, m + + def leadingzeroes(digest): + n = 0 + result = ''.join(format(x, '08b') for x in bytearray(digest)) + for c in result: + if c == '0': + n += 1 + else: + break + return n pow, pow_hash = genhash() start_time = time.time() # check to see if the first characters of the string are 0 global work - while not (pow_hash[0:work] == ("0" * work)): + lead = leadingzeroes(pow_hash.digest()) + while lead < work : # Check if any node found the solution every 60 seconds if int((time.time() - start_time) % 60) == 0: @@ -102,8 +118,9 @@ def genhash(): return False, new_blockchain # generate new hash for next time pow, pow_hash = genhash() + lead = leadingzeroes(pow_hash.digest()) # Once that hash is found, we can return it as a proof of our work - return pow, pow_hash + return pow, pow_hash.hexdigest() def mine(a, blockchain, node_pending_transactions): @@ -116,7 +133,7 @@ def mine(a, blockchain, node_pending_transactions): """ # Get the last proof of work last_block = BLOCKCHAIN[len(BLOCKCHAIN) - 1] - NODE_PENDING_TRANSACTIONS = requests.get(MINER_NODE_URL + ":"+PORT+"/txion?update=" + user.public_key).content + NODE_PENDING_TRANSACTIONS = requests.get("http://"+MINER_NODE_URL + ":"+str(PORT)+"/txion?update=" + user.public_key).content NODE_PENDING_TRANSACTIONS = json.loads(NODE_PENDING_TRANSACTIONS) # Then we add the mining reward NODE_PENDING_TRANSACTIONS.append({ @@ -128,6 +145,7 @@ def mine(a, blockchain, node_pending_transactions): # Note: The program will hang here until a new proof of work is found proof = proof_of_work(last_block, NODE_PENDING_TRANSACTIONS) + # If we didn't guess the proof, start mining again if not proof[0]: # Update blockchain and save it to file @@ -135,7 +153,6 @@ def mine(a, blockchain, node_pending_transactions): a.send(BLOCKCHAIN) continue else: - # Now we can gather the data needed to create the new block new_block_data = { "proof-of-work": proof[1], @@ -148,7 +165,7 @@ def mine(a, blockchain, node_pending_transactions): NODE_PENDING_TRANSACTIONS = [] # Now create the new block mined_block = Block(new_block_index, new_block_timestamp, new_block_data, last_block.hash) - + print(mined_block.timestamp - last_block.timestamp,mined_block) BLOCKCHAIN.append(mined_block) # Let the client know this node mined a block # print(json.dumps({ @@ -158,12 +175,14 @@ def mine(a, blockchain, node_pending_transactions): # "hash": last_block_hash # }) + "\n") a.send(BLOCKCHAIN) - requests.get(MINER_NODE_URL + ":"+PORT+"/blocks?update=" + user.public_key) + requests.get("http://"+MINER_NODE_URL + ":"+str(PORT)+"/blocks?update=" + user.public_key) def find_new_chains(): # Get the blockchains of every other node other_chains = [] + if len(other_chains) != 0: + print(PEER_NODES) for node_url in PEER_NODES: # Get their chains using a GET request blocks = None @@ -179,6 +198,8 @@ def find_new_chains(): if validated: # Add it to our list other_chains.append(blocks) + if len(other_chains) != 0: + print(PEER_NODES) return other_chains @@ -266,12 +287,13 @@ def get_blocks(): "index": str(block.index), "timestamp": str(block.timestamp), "data": str(block.data), + "previous": str(block.previous_hash), "hash": block.hash } chain_to_send_json.append(block) # Send our chain to whomever requested it - ip = request.remote_addr+":"+PORT + ip = request.remote_addr+":"+str(PORT) if str(ip) != "127.0.0.1" and ip not in PEER_NODES: PEER_NODES.append(ip) chain_to_send = json.dumps(chain_to_send_json) diff --git a/simpleCoin/miner_config.py b/simpleCoin/miner_config.py index dd431c7..1ce0f9b 100644 --- a/simpleCoin/miner_config.py +++ b/simpleCoin/miner_config.py @@ -2,7 +2,7 @@ # Port to run on PORT = 5000 # Write your node url or ip. If you are running it localhost use default -MINER_NODE_URL = "http://localhost:"+str(PORT) +MINER_NODE_URL = "127.0.0.1" # Store the url data of every other node in the network # so that we can communicate with them diff --git a/simpleCoin/scratch.py b/simpleCoin/scratch.py new file mode 100644 index 0000000..6584249 --- /dev/null +++ b/simpleCoin/scratch.py @@ -0,0 +1,39 @@ +import hashlib +import secrets +import string + +def leadingzeroes(digest): + #binary = ' '.join(map(bin,bytearray(sample_string,encoding='utf-8'))) + n = 0 + result = ''.join(format(x, '08b') for x in bytearray(digest)) + for c in result: + if c == '0': + n+=1 + else: + break + return n +def random_str(): + # Generate a random size string from 3 - 27 characters long + rand_str = '' + for i in range(0, 1 + secrets.randbelow(25)): + rand_str += string.ascii_lowercase[secrets.randbelow(26)] # each char is a random downcase letter [a-z] + return rand_str + + +work = 13 +for i in range(0,5): + m = hashlib.sha256() + m.update(random_str().encode('utf-8')) + test = m.hexdigest() + #while test[0:work] != "0"*work: + n = leadingzeroes(m.digest()) + while n < work: + m = None + r = None + m = hashlib.sha256() + r = random_str() + m.update(r.encode('utf-8')) + test = m.hexdigest() + n = leadingzeroes(m.digest()) + + print(test,leadingzeroes(m.digest())) From fc10ca6635b36e19e8d16d0acd8d9133c70ac8e8 Mon Sep 17 00:00:00 2001 From: Horological Date: Tue, 11 Sep 2018 09:49:26 -0400 Subject: [PATCH 09/56] changed structure of Block due to oversight --- simpleCoin/Block.py | 6 ++++-- simpleCoin/miner.py | 7 ++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/simpleCoin/Block.py b/simpleCoin/Block.py index 4da8e17..fd9a5db 100644 --- a/simpleCoin/Block.py +++ b/simpleCoin/Block.py @@ -1,6 +1,6 @@ import hashlib class Block: - def __init__(self, index, timestamp, data, previous_hash): + def __init__(self, index, timestamp, effort, data, previous_hash): """Returns a new Block object. Each block is "chained" to its previous by calling its unique hash. @@ -20,6 +20,8 @@ def __init__(self, index, timestamp, data, previous_hash): """ self.index = index self.timestamp = timestamp + + self.effort = effort self.data = data ''' data contains: @@ -50,4 +52,4 @@ def __repr__(self): return "Block({},{},{},\"{}\")".format(self.index,self.timestamp,self.data,self.previous_hash,self.hash) def __str__(self): - return "i: {} time: {} data: {} previous: {} hash: {}".format(self.index, self.timestamp, self.data, self.previous_hash, self.hash) \ No newline at end of file + return "i: {} time: {} effort: {} data: {} previous: {} hash: {}".format(self.index, self.timestamp, self.effort, self.data, self.previous_hash, self.hash) \ No newline at end of file diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 502403d..3b28b54 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -34,7 +34,7 @@ node.config['SQLALCHEMY_DATABASE_URI'] = "" node.config['SECRET_KEY'] = user.secret_key -work = 21 +work = 22 try: assert work > 0 and work < 65 except AssertionError: @@ -49,7 +49,7 @@ def create_genesis_block(): pad = "1337" for i in range(4, 64): pow += pad[i % len(pad)] - b = Block(0, time.time(), { + b = Block(0, time.time(), "",{ "proof-of-work": pow, "transactions": None}, "0") @@ -154,6 +154,7 @@ def mine(a, blockchain, node_pending_transactions): continue else: # Now we can gather the data needed to create the new block + new_block_effort = proof[0] new_block_data = { "proof-of-work": proof[1], "transactions": list(NODE_PENDING_TRANSACTIONS) @@ -164,7 +165,7 @@ def mine(a, blockchain, node_pending_transactions): # Empty transaction list NODE_PENDING_TRANSACTIONS = [] # Now create the new block - mined_block = Block(new_block_index, new_block_timestamp, new_block_data, last_block.hash) + mined_block = Block(new_block_index, new_block_timestamp, new_block_effort,new_block_data, last_block.hash) print(mined_block.timestamp - last_block.timestamp,mined_block) BLOCKCHAIN.append(mined_block) # Let the client know this node mined a block From 675e97e5ef14944bb956005c419654385d0a2c0f Mon Sep 17 00:00:00 2001 From: HourGlss Date: Tue, 11 Sep 2018 10:11:27 -0400 Subject: [PATCH 10/56] changed amt of work needed per block --- simpleCoin/miner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 3b28b54..4e814d9 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -34,7 +34,7 @@ node.config['SQLALCHEMY_DATABASE_URI'] = "" node.config['SECRET_KEY'] = user.secret_key -work = 22 +work = 24 try: assert work > 0 and work < 65 except AssertionError: From 8769981b35d27e11576c5c142f402764535080a1 Mon Sep 17 00:00:00 2001 From: Horological Date: Tue, 11 Sep 2018 10:25:07 -0400 Subject: [PATCH 11/56] dumped the proof of work --- simpleCoin/miner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 4e814d9..26dcdb4 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -34,7 +34,7 @@ node.config['SQLALCHEMY_DATABASE_URI'] = "" node.config['SECRET_KEY'] = user.secret_key -work = 24 +work = 1 try: assert work > 0 and work < 65 except AssertionError: From 52f41286976916cc6c14eeaf9487c6caf5474786 Mon Sep 17 00:00:00 2001 From: Horological Date: Tue, 11 Sep 2018 11:54:37 -0400 Subject: [PATCH 12/56] made a current user for github --- simpleCoin/user.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/simpleCoin/user.py b/simpleCoin/user.py index b25b038..92c5542 100644 --- a/simpleCoin/user.py +++ b/simpleCoin/user.py @@ -1,6 +1,7 @@ import hashlib +password = "github" m = hashlib.sha3_256() -m.update("This is your password now!".encode('utf-8')) +m.update(password.encode('utf-8')) secret_key = m.hexdigest() -private_key = "b87cfd49cfe5d3d0ef64094f97e40435cd0e0087661ea97a0679b97f7f2e0fc7" -public_key = "9ZTW4v76LnVTZUQu9mZrFru/0IEAc6xQJqb/OpSYFQ90eQvpbUZmn140WhvlidWrMsWA2jTaz8cKEtSX0nlTmw==" \ No newline at end of file +private_key = "0529e7d13b2c56ececbe1579f27bb9a4e20f404d96c64d3101af5cd9054c6b90" +public_key = "OdKGVzvZb71iXV+HxM8tCmigtMqW0kF0fJahzZOy03xoIc8fZWjENh99qJcmZP1m6nKodgwA+wDVemDrijzunA==" \ No newline at end of file From e378fe10bab0da69d64a483f70594b06c976e32f Mon Sep 17 00:00:00 2001 From: Horological Date: Tue, 11 Sep 2018 12:28:44 -0400 Subject: [PATCH 13/56] Wallet was generating non-usable keys? I'll have to fix the encoding. --- simpleCoin/user.py | 4 ++-- simpleCoin/wallet.py | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/simpleCoin/user.py b/simpleCoin/user.py index 92c5542..63d9dca 100644 --- a/simpleCoin/user.py +++ b/simpleCoin/user.py @@ -3,5 +3,5 @@ m = hashlib.sha3_256() m.update(password.encode('utf-8')) secret_key = m.hexdigest() -private_key = "0529e7d13b2c56ececbe1579f27bb9a4e20f404d96c64d3101af5cd9054c6b90" -public_key = "OdKGVzvZb71iXV+HxM8tCmigtMqW0kF0fJahzZOy03xoIc8fZWjENh99qJcmZP1m6nKodgwA+wDVemDrijzunA==" \ No newline at end of file +private_key = "04c64a452974be72ff789fa504a4322925e98a510a986309abafc63e4143b26d" +public_key = "FNHlQZtOXBoUGiUL3qcOLppy5UuakcYaNrs6KeEMXVUHDOqGWwRjGswBVcXlT4R3B2MDY1dYZelcq4OjMeQ00g==" \ No newline at end of file diff --git a/simpleCoin/wallet.py b/simpleCoin/wallet.py index 545c947..4dff728 100644 --- a/simpleCoin/wallet.py +++ b/simpleCoin/wallet.py @@ -104,6 +104,13 @@ def generate_ECDSA_keys(): public_key = vk.to_string().hex() #we are going to encode the public key to make it shorter public_key = base64.b64encode(bytes.fromhex(public_key)) + while "+" in public_key.decode() or "+" in private_key: + sk = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1) # this is your sign (private key) + private_key = sk.to_string().hex() # convert your private key to hex + vk = sk.get_verifying_key() # this is your verification key (public key) + public_key = vk.to_string().hex() + # we are going to encode the public key to make it shorter + public_key = base64.b64encode(bytes.fromhex(public_key)) filename = input("Write the name of your new address: ") + ".txt" with open(filename, "w") as f: From 7a2ddba451a1095b20d76ffaec6d9606f42563a3 Mon Sep 17 00:00:00 2001 From: Horological Date: Tue, 11 Sep 2018 14:01:59 -0400 Subject: [PATCH 14/56] something is going on with the Pipe --- simpleCoin/miner.py | 70 +++++++++++++++++++++++++++++++++------------ simpleCoin/pipe.txt | 65 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 19 deletions(-) create mode 100644 simpleCoin/pipe.txt diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 26dcdb4..d310d2b 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -16,7 +16,6 @@ from simpleCoin.Block import Block from simpleCoin.miner_config import MINER_NODE_URL, PEER_NODES, PORT - try: assert user.public_key != "" and user.private_key != "" except AssertionError: @@ -28,17 +27,17 @@ log = logging.getLogger('werkzeug') log.setLevel(logging.ERROR) - - node = Flask(__name__) node.config['SQLALCHEMY_DATABASE_URI'] = "" node.config['SECRET_KEY'] = user.secret_key -work = 1 +work = 4 try: assert work > 0 and work < 65 except AssertionError: print("Work value must be greater than 0 and less than 65") + + def create_genesis_block(): """To create each block, it needs the hash of the previous one. First block has no previous, so it must be created manually (with index zero @@ -49,7 +48,7 @@ def create_genesis_block(): pad = "1337" for i in range(4, 64): pow += pad[i % len(pad)] - b = Block(0, time.time(), "",{ + b = Block(0, time.time(), "", { "proof-of-work": pow, "transactions": None}, "0") @@ -74,6 +73,8 @@ def create_genesis_block(): def proof_of_work(last_block, transactions): + # if last_block.index > 0: + # print("proof of work") data = {"transactions": list(transactions)} pow = "" @@ -107,7 +108,7 @@ def leadingzeroes(digest): # check to see if the first characters of the string are 0 global work lead = leadingzeroes(pow_hash.digest()) - while lead < work : + while lead < work: # Check if any node found the solution every 60 seconds if int((time.time() - start_time) % 60) == 0: @@ -125,6 +126,8 @@ def leadingzeroes(digest): def mine(a, blockchain, node_pending_transactions): global BLOCKCHAIN + # if BLOCKCHAIN[len(BLOCKCHAIN)-1].index > 0: + # print("Mine") NODE_PENDING_TRANSACTIONS = node_pending_transactions while True: """Mining is the only way that new coins can be created. @@ -133,8 +136,12 @@ def mine(a, blockchain, node_pending_transactions): """ # Get the last proof of work last_block = BLOCKCHAIN[len(BLOCKCHAIN) - 1] - NODE_PENDING_TRANSACTIONS = requests.get("http://"+MINER_NODE_URL + ":"+str(PORT)+"/txion?update=" + user.public_key).content + # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: + # print("mine - before node_pending") + + NODE_PENDING_TRANSACTIONS = requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/txion?update=" + user.public_key).content NODE_PENDING_TRANSACTIONS = json.loads(NODE_PENDING_TRANSACTIONS) + # Then we add the mining reward NODE_PENDING_TRANSACTIONS.append({ "from": "network", @@ -145,7 +152,8 @@ def mine(a, blockchain, node_pending_transactions): # Note: The program will hang here until a new proof of work is found proof = proof_of_work(last_block, NODE_PENDING_TRANSACTIONS) - + # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: + # print("mine - after node_pending") # If we didn't guess the proof, start mining again if not proof[0]: # Update blockchain and save it to file @@ -165,8 +173,9 @@ def mine(a, blockchain, node_pending_transactions): # Empty transaction list NODE_PENDING_TRANSACTIONS = [] # Now create the new block - mined_block = Block(new_block_index, new_block_timestamp, new_block_effort,new_block_data, last_block.hash) - print(mined_block.timestamp - last_block.timestamp,mined_block) + + mined_block = Block(new_block_index, new_block_timestamp, new_block_effort, new_block_data, last_block.hash) + print(mined_block.timestamp - last_block.timestamp, mined_block) BLOCKCHAIN.append(mined_block) # Let the client know this node mined a block # print(json.dumps({ @@ -175,11 +184,22 @@ def mine(a, blockchain, node_pending_transactions): # "data": new_block_data, # "hash": last_block_hash # }) + "\n") + # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: + # print("mine - before a.send") + # print("closed",a.closed) + # print("writable", a.writable) a.send(BLOCKCHAIN) + # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: + # print("mine - after a.send") requests.get("http://"+MINER_NODE_URL + ":"+str(PORT)+"/blocks?update=" + user.public_key) + # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: + # print("mine - after requests.get") def find_new_chains(): + # global BLOCKCHAIN + # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: + # print("Find New Chains") # Get the blockchains of every other node other_chains = [] if len(other_chains) != 0: @@ -188,7 +208,7 @@ def find_new_chains(): # Get their chains using a GET request blocks = None try: - blocks = requests.get(node_url+":"+PORT + "/blocks").content + blocks = requests.get(node_url + ":" + PORT + "/blocks").content except: pass # Convert the JSON object to a Python dictionary @@ -205,10 +225,12 @@ def find_new_chains(): def consensus(): + global BLOCKCHAIN + # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: + # print("Consensus") # Get the blocks from other nodes other_chains = find_new_chains() # If our chain isn't longest, then we store the longest chain - global BLOCKCHAIN longest_chain = BLOCKCHAIN for chain in other_chains: if longest_chain == BLOCKCHAIN: @@ -226,6 +248,9 @@ def consensus(): def validate_blockchain(blockchain): + # global BLOCKCHAIN + # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: + # print("validate_blockchain") global work previous = "" @@ -251,6 +276,9 @@ def validate_blockchain(blockchain): def validate_signature(public_key, signature, message): + # global BLOCKCHAIN + # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: + # print("verify_signature") """Verifies if the signature is correct. This is used to prove it's you (and not someone else) trying to do a transaction with your address. Called when a user tries to submit a new transaction. @@ -276,9 +304,11 @@ def welcome_msg(): @node.route('/blocks', methods=['GET']) def get_blocks(): + global BLOCKCHAIN + # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: + # print("get_blocks") # Load current blockchain. Only you should update your blockchain if request.args.get("update") == user.public_key: - global BLOCKCHAIN BLOCKCHAIN = b.recv() chain_to_send = BLOCKCHAIN # Converts our blocks into dictionaries so we can send them as json objects later @@ -294,7 +324,7 @@ def get_blocks(): chain_to_send_json.append(block) # Send our chain to whomever requested it - ip = request.remote_addr+":"+str(PORT) + ip = request.remote_addr + ":" + str(PORT) if str(ip) != "127.0.0.1" and ip not in PEER_NODES: PEER_NODES.append(ip) chain_to_send = json.dumps(chain_to_send_json) @@ -303,9 +333,9 @@ def get_blocks(): @node.route('/txion', methods=['GET', 'POST']) def transaction(): - """Each transaction sent to this node gets validated and submitted. - Then it waits to be added to the blockchain. Transactions only move coins, they don't create it. - """ + # global BLOCKCHAIN + # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: + # print("transaction") if request.method == 'POST': # On each new POST request, we extract the transaction data @@ -321,12 +351,12 @@ def transaction(): print("AMOUNT: {0}\n".format(new_txion['amount'])) # Then we let the client know it worked out - #Push to all other available nodes + # Push to all other available nodes for node_url in PEER_NODES: if node_url != request.remote_addr: try: headers = {"Content-Type": "application/json"} - requests.post(node_url+":"+PORT+"/txion",json = new_txion,headers = headers) + requests.post(node_url + ":" + PORT + "/txion", json=new_txion, headers=headers) except: pass return "Transaction submission successful\n" @@ -343,6 +373,8 @@ def transaction(): @node.route('/balances', methods=['GET']) def get_balance(): global BLOCKCHAIN + # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: + # print("Balances") working = BLOCKCHAIN balances = {} balances_json = [] diff --git a/simpleCoin/pipe.txt b/simpleCoin/pipe.txt new file mode 100644 index 0000000..b6df043 --- /dev/null +++ b/simpleCoin/pipe.txt @@ -0,0 +1,65 @@ +class PipeConnection(_ConnectionBase) + | Connection class based on a Windows named pipe. + | Overlapped I/O is used, so the handles must have been created + | with FILE_FLAG_OVERLAPPED. + | + | Method resolution order: + | PipeConnection + | _ConnectionBase + | builtins.object + | + | Methods inherited from _ConnectionBase: + | + | __del__(self) + | + | __enter__(self) + | + | __exit__(self, exc_type, exc_value, exc_tb) + | + | __init__(self, handle, readable=True, writable=True) + | Initialize self. See help(type(self)) for accurate signature. + | + | close(self) + | Close the connection + | + | fileno(self) + | File descriptor or handle of the connection + | + | poll(self, timeout=0.0) + | Whether there is any input available to be read + | + | recv(self) + | Receive a (picklable) object + | + | recv_bytes(self, maxlength=None) + | Receive bytes data as a bytes object. + | + | recv_bytes_into(self, buf, offset=0) + | Receive bytes data into a writeable bytes-like object. + | Return the number of bytes read. + | + | send(self, obj) + | Send a (picklable) object + | + | send_bytes(self, buf, offset=0, size=None) + | Send the bytes data from a bytes-like object + | + | ---------------------------------------------------------------------- + | Data descriptors inherited from _ConnectionBase: + | + | __dict__ + | dictionary for instance variables (if defined) + | + | __weakref__ + | list of weak references to the object (if defined) + | + | closed + | True if the connection is closed + | + | readable + | True if the connection is readable + | + | writable + | True if the connection is writable + +None \ No newline at end of file From 1ab037d26ac01a62928863b30b84801b01fa137c Mon Sep 17 00:00:00 2001 From: Horological Date: Tue, 11 Sep 2018 15:35:46 -0400 Subject: [PATCH 15/56] Queue now instead of Pipe. we no longer need sql for storing the blockchain yet, not even close. --- simpleCoin/miner.py | 31 +++++++++++++++--------------- simpleCoin/scratch.py | 44 +++++-------------------------------------- 2 files changed, 21 insertions(+), 54 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index d310d2b..5d24680 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -3,11 +3,12 @@ import sys import json import requests +import os import secrets import string import base64 from flask import Flask, request -from multiprocessing import Process, Pipe +from multiprocessing import Process, Queue import ecdsa import secrets import string @@ -31,7 +32,7 @@ node.config['SQLALCHEMY_DATABASE_URI'] = "" node.config['SECRET_KEY'] = user.secret_key -work = 4 +work = 8 try: assert work > 0 and work < 65 except AssertionError: @@ -63,7 +64,6 @@ def create_genesis_block(): # Node's blockchain copy BLOCKCHAIN = [create_genesis_block()] -print(BLOCKCHAIN[0]) """ Stores the transactions that this node has in a list. If the node you sent the transaction adds a block it will get accepted, but there is a chance it gets @@ -158,7 +158,7 @@ def mine(a, blockchain, node_pending_transactions): if not proof[0]: # Update blockchain and save it to file BLOCKCHAIN = proof[1] - a.send(BLOCKCHAIN) + a.put(BLOCKCHAIN) continue else: # Now we can gather the data needed to create the new block @@ -186,9 +186,7 @@ def mine(a, blockchain, node_pending_transactions): # }) + "\n") # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: # print("mine - before a.send") - # print("closed",a.closed) - # print("writable", a.writable) - a.send(BLOCKCHAIN) + a.put(BLOCKCHAIN) # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: # print("mine - after a.send") requests.get("http://"+MINER_NODE_URL + ":"+str(PORT)+"/blocks?update=" + user.public_key) @@ -202,10 +200,11 @@ def find_new_chains(): # print("Find New Chains") # Get the blockchains of every other node other_chains = [] - if len(other_chains) != 0: - print(PEER_NODES) + # if len(other_chains) != 0: + # print(PEER_NODES) for node_url in PEER_NODES: # Get their chains using a GET request + blocks = None try: blocks = requests.get(node_url + ":" + PORT + "/blocks").content @@ -219,8 +218,8 @@ def find_new_chains(): if validated: # Add it to our list other_chains.append(blocks) - if len(other_chains) != 0: - print(PEER_NODES) + # if len(other_chains) != 0: + # print(PEER_NODES) return other_chains @@ -309,7 +308,10 @@ def get_blocks(): # print("get_blocks") # Load current blockchain. Only you should update your blockchain if request.args.get("update") == user.public_key: - BLOCKCHAIN = b.recv() + # print("updating /blocks") + if not a.empty(): + # print("b was not empty") + BLOCKCHAIN = a.get() chain_to_send = BLOCKCHAIN # Converts our blocks into dictionaries so we can send them as json objects later chain_to_send_json = [] @@ -408,10 +410,9 @@ def get_balance(): if __name__ == '__main__': welcome_msg() - # Start mining - a, b = Pipe() + a = Queue() p1 = Process(target=mine, args=(a, BLOCKCHAIN, NODE_PENDING_TRANSACTIONS)) p1.start() # Start server to receive transactions - p2 = Process(target=node.run(host="0.0.0.0", port=PORT), args=b) + p2 = Process(target=node.run(host="0.0.0.0", port=PORT), args=a) p2.start() diff --git a/simpleCoin/scratch.py b/simpleCoin/scratch.py index 6584249..70d381d 100644 --- a/simpleCoin/scratch.py +++ b/simpleCoin/scratch.py @@ -1,39 +1,5 @@ -import hashlib -import secrets -import string - -def leadingzeroes(digest): - #binary = ' '.join(map(bin,bytearray(sample_string,encoding='utf-8'))) - n = 0 - result = ''.join(format(x, '08b') for x in bytearray(digest)) - for c in result: - if c == '0': - n+=1 - else: - break - return n -def random_str(): - # Generate a random size string from 3 - 27 characters long - rand_str = '' - for i in range(0, 1 + secrets.randbelow(25)): - rand_str += string.ascii_lowercase[secrets.randbelow(26)] # each char is a random downcase letter [a-z] - return rand_str - - -work = 13 -for i in range(0,5): - m = hashlib.sha256() - m.update(random_str().encode('utf-8')) - test = m.hexdigest() - #while test[0:work] != "0"*work: - n = leadingzeroes(m.digest()) - while n < work: - m = None - r = None - m = hashlib.sha256() - r = random_str() - m.update(r.encode('utf-8')) - test = m.hexdigest() - n = leadingzeroes(m.digest()) - - print(test,leadingzeroes(m.digest())) +x = input("give me a string\n") +y = input("give me a letter\n") +y = ord(y) +output = "".join([chr((((ord(c)-97) + (y-96)) % 26) + 97) for c in x]) +print(output) \ No newline at end of file From f223a327b2952b9a6abe69ec3da84a176c7cf96f Mon Sep 17 00:00:00 2001 From: Horological Date: Tue, 11 Sep 2018 21:06:01 -0400 Subject: [PATCH 16/56] fixed for effort --- simpleCoin/Block.py | 2 +- simpleCoin/miner.py | 78 ++++++++++----------------------------------- 2 files changed, 17 insertions(+), 63 deletions(-) diff --git a/simpleCoin/Block.py b/simpleCoin/Block.py index fd9a5db..e470e0c 100644 --- a/simpleCoin/Block.py +++ b/simpleCoin/Block.py @@ -49,7 +49,7 @@ def validate(self,effort): return True def __repr__(self): - return "Block({},{},{},\"{}\")".format(self.index,self.timestamp,self.data,self.previous_hash,self.hash) + return "Block({},{},'{}',{},'{}')".format(self.index,self.timestamp,self.effort,self.data,self.previous_hash) def __str__(self): return "i: {} time: {} effort: {} data: {} previous: {} hash: {}".format(self.index, self.timestamp, self.effort, self.data, self.previous_hash, self.hash) \ No newline at end of file diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 5d24680..b84b216 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -23,13 +23,11 @@ print("You need to generate keys in your wallet") sys.exit() -from flask_sqlalchemy import SQLAlchemy log = logging.getLogger('werkzeug') log.setLevel(logging.ERROR) node = Flask(__name__) -node.config['SQLALCHEMY_DATABASE_URI'] = "" node.config['SECRET_KEY'] = user.secret_key work = 8 @@ -49,16 +47,10 @@ def create_genesis_block(): pad = "1337" for i in range(4, 64): pow += pad[i % len(pad)] - b = Block(0, time.time(), "", { + b = Block(0, time.time(), "e", { "proof-of-work": pow, "transactions": None}, "0") - # print(json.dumps({ - # "index": b.index, - # "timestamp": str(b.timestamp), - # "data": b.data, - # "hash": b.hash - # }) + "\n") return b @@ -73,8 +65,6 @@ def create_genesis_block(): def proof_of_work(last_block, transactions): - # if last_block.index > 0: - # print("proof of work") data = {"transactions": list(transactions)} pow = "" @@ -105,7 +95,6 @@ def leadingzeroes(digest): pow, pow_hash = genhash() start_time = time.time() - # check to see if the first characters of the string are 0 global work lead = leadingzeroes(pow_hash.digest()) while lead < work: @@ -126,8 +115,6 @@ def leadingzeroes(digest): def mine(a, blockchain, node_pending_transactions): global BLOCKCHAIN - # if BLOCKCHAIN[len(BLOCKCHAIN)-1].index > 0: - # print("Mine") NODE_PENDING_TRANSACTIONS = node_pending_transactions while True: """Mining is the only way that new coins can be created. @@ -136,8 +123,6 @@ def mine(a, blockchain, node_pending_transactions): """ # Get the last proof of work last_block = BLOCKCHAIN[len(BLOCKCHAIN) - 1] - # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: - # print("mine - before node_pending") NODE_PENDING_TRANSACTIONS = requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/txion?update=" + user.public_key).content NODE_PENDING_TRANSACTIONS = json.loads(NODE_PENDING_TRANSACTIONS) @@ -148,20 +133,13 @@ def mine(a, blockchain, node_pending_transactions): "to": user.public_key, "amount": 1.0}) - # Find the proof of work for the current block being mined - # Note: The program will hang here until a new proof of work is found proof = proof_of_work(last_block, NODE_PENDING_TRANSACTIONS) - # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: - # print("mine - after node_pending") - # If we didn't guess the proof, start mining again if not proof[0]: - # Update blockchain and save it to file BLOCKCHAIN = proof[1] a.put(BLOCKCHAIN) continue else: - # Now we can gather the data needed to create the new block new_block_effort = proof[0] new_block_data = { "proof-of-work": proof[1], @@ -170,63 +148,41 @@ def mine(a, blockchain, node_pending_transactions): new_block_index = last_block.index + 1 new_block_timestamp = time.time() - # Empty transaction list NODE_PENDING_TRANSACTIONS = [] - # Now create the new block mined_block = Block(new_block_index, new_block_timestamp, new_block_effort, new_block_data, last_block.hash) print(mined_block.timestamp - last_block.timestamp, mined_block) BLOCKCHAIN.append(mined_block) - # Let the client know this node mined a block - # print(json.dumps({ - # "index": new_block_index, - # "timestamp": str(new_block_timestamp), - # "data": new_block_data, - # "hash": last_block_hash - # }) + "\n") - # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: - # print("mine - before a.send") a.put(BLOCKCHAIN) - # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: - # print("mine - after a.send") requests.get("http://"+MINER_NODE_URL + ":"+str(PORT)+"/blocks?update=" + user.public_key) - # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: - # print("mine - after requests.get") def find_new_chains(): - # global BLOCKCHAIN - # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: - # print("Find New Chains") + #TODO maybe check the length of nodes before just downloading one at random. + #TODO also if it fails validation, I never want to use that person again. # Get the blockchains of every other node other_chains = [] - # if len(other_chains) != 0: - # print(PEER_NODES) for node_url in PEER_NODES: - # Get their chains using a GET request - - blocks = None + blockchains = None try: - blocks = requests.get(node_url + ":" + PORT + "/blocks").content + blockchains = requests.get(node_url + ":" + PORT + "/blocks").content except: pass # Convert the JSON object to a Python dictionary - if blocks is not None: - blocks = json.loads(blocks) + if blockchains is not None: + blockchains = json.loads(blockchains) # Verify other node block is correct - validated = validate_blockchain(blocks) + validated = validate_blockchain(blockchains) if validated: - # Add it to our list - other_chains.append(blocks) - # if len(other_chains) != 0: - # print(PEER_NODES) + other_chains.append(blockchains) return other_chains def consensus(): + #TODO I should look at the hashes of my coins versus there's and then only validate when they differ + if len(PEER_NODES) == 0: + return False global BLOCKCHAIN - # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: - # print("Consensus") # Get the blocks from other nodes other_chains = find_new_chains() # If our chain isn't longest, then we store the longest chain @@ -247,9 +203,6 @@ def consensus(): def validate_blockchain(blockchain): - # global BLOCKCHAIN - # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: - # print("validate_blockchain") global work previous = "" @@ -263,9 +216,10 @@ def validate_blockchain(blockchain): previous = block.hash continue else: - sha = hashlib.sha256() - sha.update((str(block.index) + str(block.timestamp) + str(block.data) + str(block.previous_hash)).encode('utf-8')) - if sha.hexdigest() != block.hash: + m = hashlib.sha256() + #m.update((str(last_block.index) + str(last_block.timestamp) + str(data) + str(last_block.previous_hash)).encode('utf-8')) + m.update((str(block.index) + str(block.timestamp) + str(block.data) + str(block.previous_hash)).encode('utf-8')) + if m.hexdigest() != block.hash: return False if previous != block.previous_hash: return False From 1ac5ac07b2a654ecfd3dd3874e6395752e8a490b Mon Sep 17 00:00:00 2001 From: HourGlss Date: Tue, 11 Sep 2018 22:43:26 -0400 Subject: [PATCH 17/56] Fixed Validation and structure of block creation --- simpleCoin/Block.py | 37 ++++++++-------- simpleCoin/miner.py | 98 ++++++++++++++++++++++++++----------------- simpleCoin/pipe.txt | 65 ---------------------------- simpleCoin/scratch.py | 54 +++++++++++++++++++++--- 4 files changed, 127 insertions(+), 127 deletions(-) delete mode 100644 simpleCoin/pipe.txt diff --git a/simpleCoin/Block.py b/simpleCoin/Block.py index e470e0c..63dff55 100644 --- a/simpleCoin/Block.py +++ b/simpleCoin/Block.py @@ -1,6 +1,6 @@ import hashlib -class Block: - def __init__(self, index, timestamp, effort, data, previous_hash): +class Block(): + def __init__(self, index, timestamp, pow, effort,data, previous_hash): """Returns a new Block object. Each block is "chained" to its previous by calling its unique hash. @@ -21,35 +21,36 @@ def __init__(self, index, timestamp, effort, data, previous_hash): self.index = index self.timestamp = timestamp + self.proof_of_work = pow self.effort = effort self.data = data ''' data contains: - proof-of-work (str) - transactions: (list?) - + transactions: list ''' self.previous_hash = previous_hash self.hash = self.hash_block() def hash_block(self): """Creates the unique hash for the block. It uses sha256.""" - sha = hashlib.sha256() - sha.update((str(self.index) + str(self.timestamp) + str(self.data) + str(self.previous_hash)).encode('utf-8')) - return sha.hexdigest() + m = hashlib.sha256() + m.update((str(self.index) + str(self.timestamp) +str(self.proof_of_work)+ str(self.effort) + str(self.data) + str(self.previous_hash)).encode('utf-8')) + return m.hexdigest() - def validate(self,effort): - ''' - :param effort: number of digits of zero in proof of work - :return: True or False if this block is valid - ''' - if self.data['proof-of-work'][0:effort] != "0"*effort: - return False - return True def __repr__(self): - return "Block({},{},'{}',{},'{}')".format(self.index,self.timestamp,self.effort,self.data,self.previous_hash) + #def __init__(self, index, timestamp, pow, effort,data, previous_hash): + return "Block({},{},'{}','{}',{},'{}')".format(self.index,self.timestamp,self.proof_of_work,self.effort,self.data,self.previous_hash) def __str__(self): - return "i: {} time: {} effort: {} data: {} previous: {} hash: {}".format(self.index, self.timestamp, self.effort, self.data, self.previous_hash, self.hash) \ No newline at end of file + return "i: {} time: {} \tpow: {} effort: {} data: {} \tprevious: {} hash: {}".format(self.index, self.timestamp,self.proof_of_work, self.effort, self.data, self.previous_hash, self.hash) + +def buildpow(index,timestamp,effort,data,previous_hash): + m = hashlib.sha256() + m.update((str(index) + str(timestamp) + str(effort) + str(data) + str(previous_hash)).encode('utf-8')) + return m +def validate(block): + pow = buildpow(block.index,block.timestamp,block.effort,block.data,block.previous_hash) + if block.proof_of_work == pow.hexdigest(): + return True \ No newline at end of file diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index b84b216..dbed0e5 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -14,7 +14,7 @@ import string import logging import simpleCoin.user as user -from simpleCoin.Block import Block +from simpleCoin.Block import Block,buildpow from simpleCoin.miner_config import MINER_NODE_URL, PEER_NODES, PORT try: @@ -23,14 +23,13 @@ print("You need to generate keys in your wallet") sys.exit() - log = logging.getLogger('werkzeug') log.setLevel(logging.ERROR) node = Flask(__name__) node.config['SECRET_KEY'] = user.secret_key -work = 8 +work = 1 try: assert work > 0 and work < 65 except AssertionError: @@ -47,15 +46,14 @@ def create_genesis_block(): pad = "1337" for i in range(4, 64): pow += pad[i % len(pad)] - b = Block(0, time.time(), "e", { - "proof-of-work": pow, + b = Block(0, time.time(), pow, "e", { "transactions": None}, "0") return b # Node's blockchain copy -BLOCKCHAIN = [create_genesis_block()] + """ Stores the transactions that this node has in a list. If the node you sent the transaction adds a block it will get accepted, but there is a chance it gets @@ -63,10 +61,16 @@ def create_genesis_block(): processed""" NODE_PENDING_TRANSACTIONS = [] +BLOCKCHAIN = [create_genesis_block()] +print("b0 =",repr(BLOCKCHAIN[0])) +print("#",BLOCKCHAIN[0]) +def proof_of_work(last_block, data): + + new_block_index = last_block.index + 1 + new_block_timestamp = time.time() + + NODE_PENDING_TRANSACTIONS = [] -def proof_of_work(last_block, transactions): - data = {"transactions": list(transactions)} - pow = "" def random_str(): # Generate a random size string from 3 - 27 characters long @@ -76,12 +80,8 @@ def random_str(): return rand_str def genhash(): - pow = random_str() - m = hashlib.sha3_256() - data["proof-of-work"] = pow - m.update((str(last_block.index) + str(last_block.timestamp) + str(data) + str(last_block.previous_hash)).encode('utf-8')) - - return pow, m + effort = random_str() + return effort, buildpow(new_block_index,new_block_timestamp,effort,data,last_block.hash) def leadingzeroes(digest): n = 0 @@ -93,7 +93,7 @@ def leadingzeroes(digest): break return n - pow, pow_hash = genhash() + effort, pow_hash = genhash() start_time = time.time() global work lead = leadingzeroes(pow_hash.digest()) @@ -107,14 +107,17 @@ def leadingzeroes(digest): # (False: another node got proof first, new blockchain) return False, new_blockchain # generate new hash for next time - pow, pow_hash = genhash() + effort, pow_hash = genhash() lead = leadingzeroes(pow_hash.digest()) + # Once that hash is found, we can return it as a proof of our work - return pow, pow_hash.hexdigest() + mined_block = Block(new_block_index, new_block_timestamp, pow_hash.hexdigest(),effort, data, last_block.hash) + return True, mined_block def mine(a, blockchain, node_pending_transactions): global BLOCKCHAIN + global work NODE_PENDING_TRANSACTIONS = node_pending_transactions while True: """Mining is the only way that new coins can be created. @@ -124,7 +127,8 @@ def mine(a, blockchain, node_pending_transactions): # Get the last proof of work last_block = BLOCKCHAIN[len(BLOCKCHAIN) - 1] - NODE_PENDING_TRANSACTIONS = requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/txion?update=" + user.public_key).content + NODE_PENDING_TRANSACTIONS = requests.get( + "http://" + MINER_NODE_URL + ":" + str(PORT) + "/txion?update=" + user.public_key).content NODE_PENDING_TRANSACTIONS = json.loads(NODE_PENDING_TRANSACTIONS) # Then we add the mining reward @@ -133,33 +137,45 @@ def mine(a, blockchain, node_pending_transactions): "to": user.public_key, "amount": 1.0}) - - proof = proof_of_work(last_block, NODE_PENDING_TRANSACTIONS) + new_block_data = {"transactions": list(NODE_PENDING_TRANSACTIONS)} + proof = proof_of_work(last_block, new_block_data) if not proof[0]: BLOCKCHAIN = proof[1] a.put(BLOCKCHAIN) continue else: - new_block_effort = proof[0] - new_block_data = { - "proof-of-work": proof[1], - "transactions": list(NODE_PENDING_TRANSACTIONS) - } - new_block_index = last_block.index + 1 - new_block_timestamp = time.time() - - NODE_PENDING_TRANSACTIONS = [] - - mined_block = Block(new_block_index, new_block_timestamp, new_block_effort, new_block_data, last_block.hash) - print(mined_block.timestamp - last_block.timestamp, mined_block) + mined_block = proof[1] + + ''' + String + ''' + print("#",mined_block) + ''' + String + ''' + ''' + REPR + ''' + print("b{} = ".format(mined_block.index), repr(mined_block)) + if last_block.index == 1: + print('work = {}'.format(work)) + print("blockchain = [", end="") + for i in range(0, len(BLOCKCHAIN)+1): + print("b{}".format(i), end=",") + print("]") + sys.exit() + + ''' + END REPR + ''' BLOCKCHAIN.append(mined_block) a.put(BLOCKCHAIN) - requests.get("http://"+MINER_NODE_URL + ":"+str(PORT)+"/blocks?update=" + user.public_key) + requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/blocks?update=" + user.public_key) def find_new_chains(): - #TODO maybe check the length of nodes before just downloading one at random. - #TODO also if it fails validation, I never want to use that person again. + # TODO maybe check the length of nodes before just downloading one at random. + # TODO also if it fails validation, I never want to use that person again. # Get the blockchains of every other node other_chains = [] for node_url in PEER_NODES: @@ -179,7 +195,7 @@ def find_new_chains(): def consensus(): - #TODO I should look at the hashes of my coins versus there's and then only validate when they differ + # TODO I should look at the hashes of my coins versus there's and then only validate when they differ if len(PEER_NODES) == 0: return False global BLOCKCHAIN @@ -217,8 +233,9 @@ def validate_blockchain(blockchain): continue else: m = hashlib.sha256() - #m.update((str(last_block.index) + str(last_block.timestamp) + str(data) + str(last_block.previous_hash)).encode('utf-8')) - m.update((str(block.index) + str(block.timestamp) + str(block.data) + str(block.previous_hash)).encode('utf-8')) + # m.update((str(last_block.index) + str(last_block.timestamp) + str(data) + str(last_block.previous_hash)).encode('utf-8')) + m.update( + (str(block.index) + str(block.timestamp) + str(block.data) + str(block.previous_hash)).encode('utf-8')) if m.hexdigest() != block.hash: return False if previous != block.previous_hash: @@ -246,6 +263,9 @@ def validate_signature(public_key, signature, message): return False + + + def welcome_msg(): print(""" =========================================\n SIMPLE COIN v1.0.0 - BLOCKCHAIN SYSTEM\n diff --git a/simpleCoin/pipe.txt b/simpleCoin/pipe.txt deleted file mode 100644 index b6df043..0000000 --- a/simpleCoin/pipe.txt +++ /dev/null @@ -1,65 +0,0 @@ -class PipeConnection(_ConnectionBase) - | Connection class based on a Windows named pipe. - | Overlapped I/O is used, so the handles must have been created - | with FILE_FLAG_OVERLAPPED. - | - | Method resolution order: - | PipeConnection - | _ConnectionBase - | builtins.object - | - | Methods inherited from _ConnectionBase: - | - | __del__(self) - | - | __enter__(self) - | - | __exit__(self, exc_type, exc_value, exc_tb) - | - | __init__(self, handle, readable=True, writable=True) - | Initialize self. See help(type(self)) for accurate signature. - | - | close(self) - | Close the connection - | - | fileno(self) - | File descriptor or handle of the connection - | - | poll(self, timeout=0.0) - | Whether there is any input available to be read - | - | recv(self) - | Receive a (picklable) object - | - | recv_bytes(self, maxlength=None) - | Receive bytes data as a bytes object. - | - | recv_bytes_into(self, buf, offset=0) - | Receive bytes data into a writeable bytes-like object. - | Return the number of bytes read. - | - | send(self, obj) - | Send a (picklable) object - | - | send_bytes(self, buf, offset=0, size=None) - | Send the bytes data from a bytes-like object - | - | ---------------------------------------------------------------------- - | Data descriptors inherited from _ConnectionBase: - | - | __dict__ - | dictionary for instance variables (if defined) - | - | __weakref__ - | list of weak references to the object (if defined) - | - | closed - | True if the connection is closed - | - | readable - | True if the connection is readable - | - | writable - | True if the connection is writable - -None \ No newline at end of file diff --git a/simpleCoin/scratch.py b/simpleCoin/scratch.py index 70d381d..ee99334 100644 --- a/simpleCoin/scratch.py +++ b/simpleCoin/scratch.py @@ -1,5 +1,49 @@ -x = input("give me a string\n") -y = input("give me a letter\n") -y = ord(y) -output = "".join([chr((((ord(c)-97) + (y-96)) % 26) + 97) for c in x]) -print(output) \ No newline at end of file +import hashlib +from simpleCoin.Block import Block,buildpow,validate +b0 = Block(0,1536720033.1050985,'0133713371337133713371337133713371337133713371337133713371337','e',{'transactions': None},'0') +# i: 0 time: 1536720033.1050985 pow: 0133713371337133713371337133713371337133713371337133713371337 effort: e data: {'transactions': None} previous: 0 hash: f23c20d1cfcc300bf93dcb2dbca764b0b5ee572b60d1d373f9151fbf31d8bd70 +# 11536720034.1133897nrdwmclxbcjguewnfcxqs{'transactions': [{'from': 'network', 'to': 'FNHlQZtOXBoUGiUL3qcOLppy5UuakcYaNrs6KeEMXVUHDOqGWwRjGswBVcXlT4R3B2MDY1dYZelcq4OjMeQ00g==', 'amount': 1.0}]}f23c20d1cfcc300bf93dcb2dbca764b0b5ee572b60d1d373f9151fbf31d8bd70 +# i: 1 time: 1536720034.1133897 pow: 36201854fa4195c9f09f746a1639d34b5d5c34634d0e6edc5bbb11e736490a90 effort: nrdwmclxbcjguewnfcxqs data: {'transactions': [{'from': 'network', 'to': 'FNHlQZtOXBoUGiUL3qcOLppy5UuakcYaNrs6KeEMXVUHDOqGWwRjGswBVcXlT4R3B2MDY1dYZelcq4OjMeQ00g==', 'amount': 1.0}]} previous: f23c20d1cfcc300bf93dcb2dbca764b0b5ee572b60d1d373f9151fbf31d8bd70 hash: b88710787bda6449ed2f7631d6240f9e034bbc52c65027ea3efd6ca606225fdd +b1 = Block(1,1536720034.1133897,'36201854fa4195c9f09f746a1639d34b5d5c34634d0e6edc5bbb11e736490a90','nrdwmclxbcjguewnfcxqs',{'transactions': [{'from': 'network', 'to': 'FNHlQZtOXBoUGiUL3qcOLppy5UuakcYaNrs6KeEMXVUHDOqGWwRjGswBVcXlT4R3B2MDY1dYZelcq4OjMeQ00g==', 'amount': 1.0}]},'f23c20d1cfcc300bf93dcb2dbca764b0b5ee572b60d1d373f9151fbf31d8bd70') +# 21536720034.1184013gckvrsf{'transactions': [{'from': 'network', 'to': 'FNHlQZtOXBoUGiUL3qcOLppy5UuakcYaNrs6KeEMXVUHDOqGWwRjGswBVcXlT4R3B2MDY1dYZelcq4OjMeQ00g==', 'amount': 1.0}]}b88710787bda6449ed2f7631d6240f9e034bbc52c65027ea3efd6ca606225fdd +# i: 2 time: 1536720034.1184013 pow: 0ce49ef80516b73e33b9adf98c7a59f67155e0f328e0846cc3400bdf7851ba14 effort: gckvrsf data: {'transactions': [{'from': 'network', 'to': 'FNHlQZtOXBoUGiUL3qcOLppy5UuakcYaNrs6KeEMXVUHDOqGWwRjGswBVcXlT4R3B2MDY1dYZelcq4OjMeQ00g==', 'amount': 1.0}]} previous: b88710787bda6449ed2f7631d6240f9e034bbc52c65027ea3efd6ca606225fdd hash: 6e3dd1e9fea3ad2a868ddfe503827c2d7e685c366218bb3c0d26418d51203a01 +b2 = Block(2,1536720034.1184013,'0ce49ef80516b73e33b9adf98c7a59f67155e0f328e0846cc3400bdf7851ba14','gckvrsf',{'transactions': [{'from': 'network', 'to': 'FNHlQZtOXBoUGiUL3qcOLppy5UuakcYaNrs6KeEMXVUHDOqGWwRjGswBVcXlT4R3B2MDY1dYZelcq4OjMeQ00g==', 'amount': 1.0}]},'b88710787bda6449ed2f7631d6240f9e034bbc52c65027ea3efd6ca606225fdd') +work = 1 +blockchain = [b0,b1,b2] + + + +def validate_blockchain(blockchain): + global work + + def leadingzeroes(digest): + n = 0 + result = ''.join(format(x, '08b') for x in bytearray(digest)) + for c in result: + if c == '0': + n += 1 + else: + break + return n + + previous = "" + for i in range(0,len(blockchain)-1): + if blockchain[i].index == 0: + continue + + if not validate(blockchain[i]): + print("failed to validate",i) + return False + for transaction in blockchain[i].data['transactions']: + if transaction['from'] == "network" and transaction['amount'] != 1: + print("failed to transaction", i) + return False + #(index,timestamp,effort,data,previous_hash): + lead = leadingzeroes(buildpow(blockchain[i].index,blockchain[i].timestamp,blockchain[i].effort,blockchain[i].data,blockchain[i-1].hash).digest()) + if lead < work: + print("failed lead", i) + return False + + return True + +print(validate_blockchain(blockchain)) \ No newline at end of file From 4960e3a825e03368fba52f9302ebe40ecd55b0a2 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Tue, 11 Sep 2018 23:19:00 -0400 Subject: [PATCH 18/56] removed printing --- simpleCoin/miner.py | 22 +++++----- simpleCoin/scratch.py | 93 +++++++++++++++++++++---------------------- 2 files changed, 56 insertions(+), 59 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index dbed0e5..e8c9d41 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -62,8 +62,8 @@ def create_genesis_block(): NODE_PENDING_TRANSACTIONS = [] BLOCKCHAIN = [create_genesis_block()] -print("b0 =",repr(BLOCKCHAIN[0])) -print("#",BLOCKCHAIN[0]) +# print("b0 =",repr(BLOCKCHAIN[0])) +# print("#",BLOCKCHAIN[0]) def proof_of_work(last_block, data): new_block_index = last_block.index + 1 @@ -149,21 +149,21 @@ def mine(a, blockchain, node_pending_transactions): ''' String ''' - print("#",mined_block) + # print("#",mined_block) ''' String ''' ''' REPR ''' - print("b{} = ".format(mined_block.index), repr(mined_block)) - if last_block.index == 1: - print('work = {}'.format(work)) - print("blockchain = [", end="") - for i in range(0, len(BLOCKCHAIN)+1): - print("b{}".format(i), end=",") - print("]") - sys.exit() + # print("b{} = ".format(mined_block.index), repr(mined_block)) + # if last_block.index == 1: + # print('work = {}'.format(work)) + # print("blockchain = [", end="") + # for i in range(0, len(BLOCKCHAIN)+1): + # print("b{}".format(i), end=",") + # print("]") + # sys.exit() ''' END REPR diff --git a/simpleCoin/scratch.py b/simpleCoin/scratch.py index ee99334..d12ff2e 100644 --- a/simpleCoin/scratch.py +++ b/simpleCoin/scratch.py @@ -1,49 +1,46 @@ import hashlib -from simpleCoin.Block import Block,buildpow,validate -b0 = Block(0,1536720033.1050985,'0133713371337133713371337133713371337133713371337133713371337','e',{'transactions': None},'0') -# i: 0 time: 1536720033.1050985 pow: 0133713371337133713371337133713371337133713371337133713371337 effort: e data: {'transactions': None} previous: 0 hash: f23c20d1cfcc300bf93dcb2dbca764b0b5ee572b60d1d373f9151fbf31d8bd70 -# 11536720034.1133897nrdwmclxbcjguewnfcxqs{'transactions': [{'from': 'network', 'to': 'FNHlQZtOXBoUGiUL3qcOLppy5UuakcYaNrs6KeEMXVUHDOqGWwRjGswBVcXlT4R3B2MDY1dYZelcq4OjMeQ00g==', 'amount': 1.0}]}f23c20d1cfcc300bf93dcb2dbca764b0b5ee572b60d1d373f9151fbf31d8bd70 -# i: 1 time: 1536720034.1133897 pow: 36201854fa4195c9f09f746a1639d34b5d5c34634d0e6edc5bbb11e736490a90 effort: nrdwmclxbcjguewnfcxqs data: {'transactions': [{'from': 'network', 'to': 'FNHlQZtOXBoUGiUL3qcOLppy5UuakcYaNrs6KeEMXVUHDOqGWwRjGswBVcXlT4R3B2MDY1dYZelcq4OjMeQ00g==', 'amount': 1.0}]} previous: f23c20d1cfcc300bf93dcb2dbca764b0b5ee572b60d1d373f9151fbf31d8bd70 hash: b88710787bda6449ed2f7631d6240f9e034bbc52c65027ea3efd6ca606225fdd -b1 = Block(1,1536720034.1133897,'36201854fa4195c9f09f746a1639d34b5d5c34634d0e6edc5bbb11e736490a90','nrdwmclxbcjguewnfcxqs',{'transactions': [{'from': 'network', 'to': 'FNHlQZtOXBoUGiUL3qcOLppy5UuakcYaNrs6KeEMXVUHDOqGWwRjGswBVcXlT4R3B2MDY1dYZelcq4OjMeQ00g==', 'amount': 1.0}]},'f23c20d1cfcc300bf93dcb2dbca764b0b5ee572b60d1d373f9151fbf31d8bd70') -# 21536720034.1184013gckvrsf{'transactions': [{'from': 'network', 'to': 'FNHlQZtOXBoUGiUL3qcOLppy5UuakcYaNrs6KeEMXVUHDOqGWwRjGswBVcXlT4R3B2MDY1dYZelcq4OjMeQ00g==', 'amount': 1.0}]}b88710787bda6449ed2f7631d6240f9e034bbc52c65027ea3efd6ca606225fdd -# i: 2 time: 1536720034.1184013 pow: 0ce49ef80516b73e33b9adf98c7a59f67155e0f328e0846cc3400bdf7851ba14 effort: gckvrsf data: {'transactions': [{'from': 'network', 'to': 'FNHlQZtOXBoUGiUL3qcOLppy5UuakcYaNrs6KeEMXVUHDOqGWwRjGswBVcXlT4R3B2MDY1dYZelcq4OjMeQ00g==', 'amount': 1.0}]} previous: b88710787bda6449ed2f7631d6240f9e034bbc52c65027ea3efd6ca606225fdd hash: 6e3dd1e9fea3ad2a868ddfe503827c2d7e685c366218bb3c0d26418d51203a01 -b2 = Block(2,1536720034.1184013,'0ce49ef80516b73e33b9adf98c7a59f67155e0f328e0846cc3400bdf7851ba14','gckvrsf',{'transactions': [{'from': 'network', 'to': 'FNHlQZtOXBoUGiUL3qcOLppy5UuakcYaNrs6KeEMXVUHDOqGWwRjGswBVcXlT4R3B2MDY1dYZelcq4OjMeQ00g==', 'amount': 1.0}]},'b88710787bda6449ed2f7631d6240f9e034bbc52c65027ea3efd6ca606225fdd') -work = 1 -blockchain = [b0,b1,b2] - - - -def validate_blockchain(blockchain): - global work - - def leadingzeroes(digest): - n = 0 - result = ''.join(format(x, '08b') for x in bytearray(digest)) - for c in result: - if c == '0': - n += 1 - else: - break - return n - - previous = "" - for i in range(0,len(blockchain)-1): - if blockchain[i].index == 0: - continue - - if not validate(blockchain[i]): - print("failed to validate",i) - return False - for transaction in blockchain[i].data['transactions']: - if transaction['from'] == "network" and transaction['amount'] != 1: - print("failed to transaction", i) - return False - #(index,timestamp,effort,data,previous_hash): - lead = leadingzeroes(buildpow(blockchain[i].index,blockchain[i].timestamp,blockchain[i].effort,blockchain[i].data,blockchain[i-1].hash).digest()) - if lead < work: - print("failed lead", i) - return False - - return True - -print(validate_blockchain(blockchain)) \ No newline at end of file +import secrets +import string +import time +from multiprocessing import Process, Queue +import os + +def random_str(): + # Generate a random size string from 3 - 27 characters long + rand_str = '' + for i in range(0, 1 + secrets.randbelow(25)): + rand_str += string.ascii_lowercase[secrets.randbelow(26)] # each char is a random downcase letter [a-z] + return rand_str + +def createhash(): + m = hashlib.sha256() + m.update(random_str().encode(('utf-8'))) + return m.hexdigest() + +def work(q): + test = createhash() + while test[0:4] != "0"*4 : + test = createhash() + print(test) + q.put(test) + +processes = [] +if __name__ == '__main__': + q = Queue() + for i in range(os.cpu_count()-3): + print('registering process %d' % i) + processes.append(Process(target=work,args = (q,)) ) + start = time.time() + print("start: ",start) + for process in processes: + process.start() + while True: + if not q.empty(): + test = q.get() + print(test) + for process in processes: + process.terminate() + + end = time.time() + print("end: ", end) + print("delta: ", end - start) \ No newline at end of file From a4855c55b6e48ff25a09f8d09f9c36ccee0f37e3 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Tue, 11 Sep 2018 23:23:22 -0400 Subject: [PATCH 19/56] removed printing, changed export --- simpleCoin/Block.py | 10 ++++++++++ simpleCoin/miner.py | 11 ++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/simpleCoin/Block.py b/simpleCoin/Block.py index 63dff55..3f8e575 100644 --- a/simpleCoin/Block.py +++ b/simpleCoin/Block.py @@ -37,6 +37,16 @@ def hash_block(self): m.update((str(self.index) + str(self.timestamp) +str(self.proof_of_work)+ str(self.effort) + str(self.data) + str(self.previous_hash)).encode('utf-8')) return m.hexdigest() + def exportjson(self): + return { + "index": str(self.index), + "timestamp": str(self.timestamp), + "pow": str(self.proof_of_work), + "effort": str(self.effort), + "data": str(self.data), + "previous": str(self.previous_hash), + "hash": self.hash + } def __repr__(self): diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index e8c9d41..f36e7a2 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -29,7 +29,7 @@ node = Flask(__name__) node.config['SECRET_KEY'] = user.secret_key -work = 1 +work = 14 try: assert work > 0 and work < 65 except AssertionError: @@ -290,14 +290,7 @@ def get_blocks(): # Converts our blocks into dictionaries so we can send them as json objects later chain_to_send_json = [] for block in chain_to_send: - block = { - "index": str(block.index), - "timestamp": str(block.timestamp), - "data": str(block.data), - "previous": str(block.previous_hash), - "hash": block.hash - } - chain_to_send_json.append(block) + chain_to_send_json.append(block.exportjson()) # Send our chain to whomever requested it ip = request.remote_addr + ":" + str(PORT) From b2626a02a1a4e46302ed0038e245d0d6489658c9 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Wed, 12 Sep 2018 07:36:42 -0400 Subject: [PATCH 20/56] removed printing, changed export --- simpleCoin/miner.py | 26 ++++++++++++++++++++++---- simpleCoin/user.py | 6 +++--- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index f36e7a2..5fdd099 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -169,8 +169,8 @@ def mine(a, blockchain, node_pending_transactions): END REPR ''' BLOCKCHAIN.append(mined_block) - a.put(BLOCKCHAIN) - requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/blocks?update=" + user.public_key) + a.put(mined_block) + requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/block?send=" + user.public_key) def find_new_chains(): @@ -275,6 +275,16 @@ def welcome_msg(): a parallel chain.\n\n\n""") +@node.route('/block', methods=['GET']) +def get_block(): + #get incoming block + if request.args.get("update") == user.public_key: + # print("updating /blocks") + if not a.empty(): + # print("b was not empty") + BLOCKCHAIN = a.get() + + @node.route('/blocks', methods=['GET']) def get_blocks(): global BLOCKCHAIN @@ -293,9 +303,17 @@ def get_blocks(): chain_to_send_json.append(block.exportjson()) # Send our chain to whomever requested it - ip = request.remote_addr + ":" + str(PORT) + ip = request.remote_addr + print(ip) + base_url = request.base_url + print(base_url) + referrer = request.referrer + print(referrer) + print(str(request)) + print(repr(request)) if str(ip) != "127.0.0.1" and ip not in PEER_NODES: - PEER_NODES.append(ip) + PEER_NODES.append(str(ip)) + print("adding",ip,"to peers list") chain_to_send = json.dumps(chain_to_send_json) return chain_to_send diff --git a/simpleCoin/user.py b/simpleCoin/user.py index 63d9dca..e61af5f 100644 --- a/simpleCoin/user.py +++ b/simpleCoin/user.py @@ -1,7 +1,7 @@ import hashlib -password = "github" +password = "Desktop boys" m = hashlib.sha3_256() m.update(password.encode('utf-8')) secret_key = m.hexdigest() -private_key = "04c64a452974be72ff789fa504a4322925e98a510a986309abafc63e4143b26d" -public_key = "FNHlQZtOXBoUGiUL3qcOLppy5UuakcYaNrs6KeEMXVUHDOqGWwRjGswBVcXlT4R3B2MDY1dYZelcq4OjMeQ00g==" \ No newline at end of file +private_key = "6e88f8181f002b07e1a7c7b0bc7cff176865670f381e45e305939903c49bdc90" +public_key = "xICxx0YyiVg0tf5nhWPUI/WUvX0/rs/jJXUI5vTxb87VJ1w9Va7xdbRWK37/hap/5HtAAAM6X312IUJpyyAM3A==" \ No newline at end of file From 4c969545cdb5bd7ce7f31f3103346149255dae29 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Wed, 12 Sep 2018 17:45:54 -0400 Subject: [PATCH 21/56] fixed block movement --- simpleCoin/Block.py | 13 +++++++++++-- simpleCoin/miner.py | 39 +++++++++++++++++++++++---------------- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/simpleCoin/Block.py b/simpleCoin/Block.py index 3f8e575..fc041df 100644 --- a/simpleCoin/Block.py +++ b/simpleCoin/Block.py @@ -1,6 +1,6 @@ import hashlib class Block(): - def __init__(self, index, timestamp, pow, effort,data, previous_hash): + def __init__(self, index=-1, timestamp=-1, pow=-1, effort=-1,data=-1, previous_hash=-1): """Returns a new Block object. Each block is "chained" to its previous by calling its unique hash. @@ -48,6 +48,14 @@ def exportjson(self): "hash": self.hash } + def importjson(self,json): + self.index = json['index'] + self.timestamp = json['timestamp'] + self.proof_of_work = json['pow'] + self.effort = json['effort'] + self.data = json['data'] + self.previous_hash = json['previous'] + self.hash = self.hash_block() def __repr__(self): #def __init__(self, index, timestamp, pow, effort,data, previous_hash): @@ -63,4 +71,5 @@ def buildpow(index,timestamp,effort,data,previous_hash): def validate(block): pow = buildpow(block.index,block.timestamp,block.effort,block.data,block.previous_hash) if block.proof_of_work == pow.hexdigest(): - return True \ No newline at end of file + return True + return False \ No newline at end of file diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 5fdd099..f81174c 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -14,7 +14,7 @@ import string import logging import simpleCoin.user as user -from simpleCoin.Block import Block,buildpow +from simpleCoin.Block import Block,buildpow,validate from simpleCoin.miner_config import MINER_NODE_URL, PEER_NODES, PORT try: @@ -168,10 +168,18 @@ def mine(a, blockchain, node_pending_transactions): ''' END REPR ''' - BLOCKCHAIN.append(mined_block) a.put(mined_block) requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/block?send=" + user.public_key) + for node in PEER_NODES: + url = "http://" + node + ":" + str(PORT) + "/block" + data = mined_block.exportjson() + try: + requests.post(url,json = data) + except: + pass + + def find_new_chains(): # TODO maybe check the length of nodes before just downloading one at random. @@ -275,14 +283,20 @@ def welcome_msg(): a parallel chain.\n\n\n""") -@node.route('/block', methods=['GET']) +@node.route('/block', methods=['post']) def get_block(): - #get incoming block - if request.args.get("update") == user.public_key: - # print("updating /blocks") - if not a.empty(): - # print("b was not empty") - BLOCKCHAIN = a.get() + new_block_json = request.get_json() + new_block = Block().importjson(new_block_json) + if validate(new_block): + BLOCKCHAIN.append(new_block) + ip = request.remote_addr + if str(ip) != "127.0.0.1" and ip not in PEER_NODES: + PEER_NODES.append(str(ip)) + print("adding",ip,"to peers list") + + + + @node.route('/blocks', methods=['GET']) @@ -304,13 +318,6 @@ def get_blocks(): # Send our chain to whomever requested it ip = request.remote_addr - print(ip) - base_url = request.base_url - print(base_url) - referrer = request.referrer - print(referrer) - print(str(request)) - print(repr(request)) if str(ip) != "127.0.0.1" and ip not in PEER_NODES: PEER_NODES.append(str(ip)) print("adding",ip,"to peers list") From 87809cf41d8db2b8958c2194268ce4f5d083165e Mon Sep 17 00:00:00 2001 From: Horological Date: Wed, 12 Sep 2018 21:44:22 -0400 Subject: [PATCH 22/56] Attempting to fix network --- simpleCoin/miner.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index f81174c..70c2c4a 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -168,8 +168,9 @@ def mine(a, blockchain, node_pending_transactions): ''' END REPR ''' + BLOCKCHAIN.append(mined_block) a.put(mined_block) - requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/block?send=" + user.public_key) + requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/blocks?send=" + user.public_key) for node in PEER_NODES: url = "http://" + node + ":" + str(PORT) + "/block" @@ -285,15 +286,22 @@ def welcome_msg(): @node.route('/block', methods=['post']) def get_block(): + global BLOCKCHAIN new_block_json = request.get_json() - new_block = Block().importjson(new_block_json) + new_block = Block() + new_block.importjson(new_block_json) + print(new_block) if validate(new_block): + print("Validated") BLOCKCHAIN.append(new_block) + else: + print("Did not validate") + return False ip = request.remote_addr if str(ip) != "127.0.0.1" and ip not in PEER_NODES: PEER_NODES.append(str(ip)) print("adding",ip,"to peers list") - + return True From 82be7d6824eee326dbdf2c272a7e07abbc2281e3 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Wed, 12 Sep 2018 21:45:51 -0400 Subject: [PATCH 23/56] removed printing, changed export --- simpleCoin/miner.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 70c2c4a..74698a1 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -174,9 +174,10 @@ def mine(a, blockchain, node_pending_transactions): for node in PEER_NODES: url = "http://" + node + ":" + str(PORT) + "/block" + headers = {"Content-Type": "application/json"} data = mined_block.exportjson() try: - requests.post(url,json = data) + requests.post(url,json = data,header = headers,verify = False) except: pass From 1addd1ad108346e191d839d5c98f6a3ffc88d0e0 Mon Sep 17 00:00:00 2001 From: Horological Date: Wed, 12 Sep 2018 21:50:09 -0400 Subject: [PATCH 24/56] Attempting to fix network --- simpleCoin/miner.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 74698a1..e98015f 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -149,7 +149,7 @@ def mine(a, blockchain, node_pending_transactions): ''' String ''' - # print("#",mined_block) + print("#",mined_block) ''' String ''' @@ -168,8 +168,9 @@ def mine(a, blockchain, node_pending_transactions): ''' END REPR ''' + BLOCKCHAIN.append(mined_block) - a.put(mined_block) + a.put(BLOCKCHAIN) requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/blocks?send=" + user.public_key) for node in PEER_NODES: @@ -316,9 +317,8 @@ def get_blocks(): # Load current blockchain. Only you should update your blockchain if request.args.get("update") == user.public_key: # print("updating /blocks") - if not a.empty(): + BLOCKCHAIN = a.get() # print("b was not empty") - BLOCKCHAIN = a.get() chain_to_send = BLOCKCHAIN # Converts our blocks into dictionaries so we can send them as json objects later chain_to_send_json = [] From d02241c937e4f68fc774d1646825e259f8aaba47 Mon Sep 17 00:00:00 2001 From: Horological Date: Wed, 12 Sep 2018 21:58:22 -0400 Subject: [PATCH 25/56] Attempting to fix network --- simpleCoin/miner.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index e98015f..dad7de3 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -317,7 +317,9 @@ def get_blocks(): # Load current blockchain. Only you should update your blockchain if request.args.get("update") == user.public_key: # print("updating /blocks") + global BLOCKCHAIN BLOCKCHAIN = a.get() + print("block chain updated now",len(BLOCKCHAIN),"long") # print("b was not empty") chain_to_send = BLOCKCHAIN # Converts our blocks into dictionaries so we can send them as json objects later @@ -326,11 +328,8 @@ def get_blocks(): chain_to_send_json.append(block.exportjson()) # Send our chain to whomever requested it - ip = request.remote_addr - if str(ip) != "127.0.0.1" and ip not in PEER_NODES: - PEER_NODES.append(str(ip)) - print("adding",ip,"to peers list") chain_to_send = json.dumps(chain_to_send_json) + print("chain sent to ",request.remote_addr) return chain_to_send From 60e09d0b391f15b137b3d4926a5491fa482d1131 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Wed, 12 Sep 2018 22:00:56 -0400 Subject: [PATCH 26/56] removed printing, changed export --- simpleCoin/miner.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index dad7de3..b319830 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -178,9 +178,10 @@ def mine(a, blockchain, node_pending_transactions): headers = {"Content-Type": "application/json"} data = mined_block.exportjson() try: - requests.post(url,json = data,header = headers,verify = False) + response = requests.post(url,json = data,header = headers) + print(response) except: - pass + print("cannot connect to", url) From 5e4df416121cbf8601460f6b2b6457629726c4f2 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Wed, 12 Sep 2018 22:04:59 -0400 Subject: [PATCH 27/56] removed printing, changed export --- simpleCoin/miner.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index b319830..be53ffd 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -176,12 +176,9 @@ def mine(a, blockchain, node_pending_transactions): for node in PEER_NODES: url = "http://" + node + ":" + str(PORT) + "/block" headers = {"Content-Type": "application/json"} - data = mined_block.exportjson() - try: - response = requests.post(url,json = data,header = headers) - print(response) - except: - print("cannot connect to", url) + data = mined_block.exportjson(); + response = requests.post(url,json = data, headers = headers) + print(response) From 7b8b040f9d969b2fa02eef57f8018d2b7a0723a6 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Wed, 12 Sep 2018 22:06:51 -0400 Subject: [PATCH 28/56] removed printing, changed export --- simpleCoin/miner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index be53ffd..84f6ce3 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -296,12 +296,12 @@ def get_block(): BLOCKCHAIN.append(new_block) else: print("Did not validate") - return False + return "500" ip = request.remote_addr if str(ip) != "127.0.0.1" and ip not in PEER_NODES: PEER_NODES.append(str(ip)) print("adding",ip,"to peers list") - return True + return "200" From d2d18b1a9128c1d0087f0a7de7ef05096a7182aa Mon Sep 17 00:00:00 2001 From: HourGlss Date: Wed, 12 Sep 2018 22:09:06 -0400 Subject: [PATCH 29/56] fixing networking --- simpleCoin/miner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 84f6ce3..89611ab 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -171,7 +171,7 @@ def mine(a, blockchain, node_pending_transactions): BLOCKCHAIN.append(mined_block) a.put(BLOCKCHAIN) - requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/blocks?send=" + user.public_key) + requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/blocks?update=" + user.public_key) for node in PEER_NODES: url = "http://" + node + ":" + str(PORT) + "/block" From a7ae38062dd783001a3ade6741e0a70640f20549 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 16:34:35 -0400 Subject: [PATCH 30/56] Fixing networked mining --- simpleCoin/miner.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 89611ab..241557a 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -109,6 +109,11 @@ def leadingzeroes(digest): # generate new hash for next time effort, pow_hash = genhash() lead = leadingzeroes(pow_hash.digest()) + if not a.empty(): + new_block = a.get() + if validate(new_block) and new_block.previous_hash == BLOCKCHAIN[len(BLOCKCHAIN) - 1].previous_hash: + BLOCKCHAIN.append(new_block) + return False, BLOCKCHAIN # Once that hash is found, we can return it as a proof of our work mined_block = Block(new_block_index, new_block_timestamp, pow_hash.hexdigest(),effort, data, last_block.hash) @@ -149,7 +154,7 @@ def mine(a, blockchain, node_pending_transactions): ''' String ''' - print("#",mined_block) + # print("#",mined_block) ''' String ''' @@ -177,8 +182,7 @@ def mine(a, blockchain, node_pending_transactions): url = "http://" + node + ":" + str(PORT) + "/block" headers = {"Content-Type": "application/json"} data = mined_block.exportjson(); - response = requests.post(url,json = data, headers = headers) - print(response) + requests.post(url,json = data, headers = headers) @@ -291,7 +295,7 @@ def get_block(): new_block = Block() new_block.importjson(new_block_json) print(new_block) - if validate(new_block): + if validate(new_block) and new_block.previous_hash == BLOCKCHAIN[len(BLOCKCHAIN)-1].previous_hash: print("Validated") BLOCKCHAIN.append(new_block) else: From 4023b38da7a1305464e6ca32274df58462a66c7f Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 16:39:10 -0400 Subject: [PATCH 31/56] FIXING NETWORK --- simpleCoin/miner.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 241557a..a5d81bc 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -147,6 +147,8 @@ def mine(a, blockchain, node_pending_transactions): if not proof[0]: BLOCKCHAIN = proof[1] a.put(BLOCKCHAIN) + + requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/blocks?update=" + user.public_key) continue else: mined_block = proof[1] @@ -294,17 +296,17 @@ def get_block(): new_block_json = request.get_json() new_block = Block() new_block.importjson(new_block_json) - print(new_block) + # print(new_block) if validate(new_block) and new_block.previous_hash == BLOCKCHAIN[len(BLOCKCHAIN)-1].previous_hash: - print("Validated") + # print("Validated") BLOCKCHAIN.append(new_block) else: - print("Did not validate") + # print("Did not validate") return "500" ip = request.remote_addr if str(ip) != "127.0.0.1" and ip not in PEER_NODES: PEER_NODES.append(str(ip)) - print("adding",ip,"to peers list") + # print("adding",ip,"to peers list") return "200" @@ -314,14 +316,12 @@ def get_block(): @node.route('/blocks', methods=['GET']) def get_blocks(): global BLOCKCHAIN - # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: - # print("get_blocks") # Load current blockchain. Only you should update your blockchain if request.args.get("update") == user.public_key: # print("updating /blocks") - global BLOCKCHAIN + BLOCKCHAIN = a.get() - print("block chain updated now",len(BLOCKCHAIN),"long") + # print("block chain updated now",len(BLOCKCHAIN),"long") # print("b was not empty") chain_to_send = BLOCKCHAIN # Converts our blocks into dictionaries so we can send them as json objects later @@ -331,7 +331,7 @@ def get_blocks(): # Send our chain to whomever requested it chain_to_send = json.dumps(chain_to_send_json) - print("chain sent to ",request.remote_addr) + # print("chain sent to ",request.remote_addr) return chain_to_send From 24cad5981af7689f5a3afb356b48a3fdcaca9578 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 16:40:08 -0400 Subject: [PATCH 32/56] fixing networking --- simpleCoin/miner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index a5d81bc..f6f88b1 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -64,7 +64,7 @@ def create_genesis_block(): BLOCKCHAIN = [create_genesis_block()] # print("b0 =",repr(BLOCKCHAIN[0])) # print("#",BLOCKCHAIN[0]) -def proof_of_work(last_block, data): +def proof_of_work(a,last_block, data): new_block_index = last_block.index + 1 new_block_timestamp = time.time() @@ -143,7 +143,7 @@ def mine(a, blockchain, node_pending_transactions): "amount": 1.0}) new_block_data = {"transactions": list(NODE_PENDING_TRANSACTIONS)} - proof = proof_of_work(last_block, new_block_data) + proof = proof_of_work(a,last_block, new_block_data) if not proof[0]: BLOCKCHAIN = proof[1] a.put(BLOCKCHAIN) From 517ca281d8c4df7ee0294385bdde0e7690c16755 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 16:42:43 -0400 Subject: [PATCH 33/56] Fixing network --- simpleCoin/miner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index f6f88b1..dcbb577 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -299,6 +299,7 @@ def get_block(): # print(new_block) if validate(new_block) and new_block.previous_hash == BLOCKCHAIN[len(BLOCKCHAIN)-1].previous_hash: # print("Validated") + a.put(new_block) BLOCKCHAIN.append(new_block) else: # print("Did not validate") From 8ce9bef410dc6ef187b319667a8f36479a305777 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 16:48:41 -0400 Subject: [PATCH 34/56] Fixing networking --- simpleCoin/miner.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index dcbb577..1f489c6 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -60,12 +60,16 @@ def create_genesis_block(): discarded and your transaction goes back as if it was never processed""" NODE_PENDING_TRANSACTIONS = [] +BLOCKCHAIN = [] +ROOT = False +if len(PEER_NODES) == 0: + ROOT = True + BLOCKCHAIN.append(create_genesis_block()) -BLOCKCHAIN = [create_genesis_block()] # print("b0 =",repr(BLOCKCHAIN[0])) # print("#",BLOCKCHAIN[0]) def proof_of_work(a,last_block, data): - + global ROOT new_block_index = last_block.index + 1 new_block_timestamp = time.time() @@ -100,7 +104,8 @@ def leadingzeroes(digest): while lead < work: # Check if any node found the solution every 60 seconds - if int((time.time() - start_time) % 60) == 0: + if int((time.time() - start_time) % 60) == 0 or not ROOT: + ROOT = True # If any other node got the proof, stop searching new_blockchain = consensus() if new_blockchain: @@ -110,6 +115,7 @@ def leadingzeroes(digest): effort, pow_hash = genhash() lead = leadingzeroes(pow_hash.digest()) if not a.empty(): + print("got one") new_block = a.get() if validate(new_block) and new_block.previous_hash == BLOCKCHAIN[len(BLOCKCHAIN) - 1].previous_hash: BLOCKCHAIN.append(new_block) @@ -298,11 +304,11 @@ def get_block(): new_block.importjson(new_block_json) # print(new_block) if validate(new_block) and new_block.previous_hash == BLOCKCHAIN[len(BLOCKCHAIN)-1].previous_hash: - # print("Validated") + print("Validated") a.put(new_block) BLOCKCHAIN.append(new_block) else: - # print("Did not validate") + print("Did not validate") return "500" ip = request.remote_addr if str(ip) != "127.0.0.1" and ip not in PEER_NODES: From e02b2b4739bc23a798eaa2373d107e1dd92dca72 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 16:51:47 -0400 Subject: [PATCH 35/56] Fixing networks --- simpleCoin/miner.py | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 1f489c6..a25020e 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -63,6 +63,7 @@ def create_genesis_block(): BLOCKCHAIN = [] ROOT = False if len(PEER_NODES) == 0: + print("Root is true") ROOT = True BLOCKCHAIN.append(create_genesis_block()) @@ -70,8 +71,9 @@ def create_genesis_block(): # print("#",BLOCKCHAIN[0]) def proof_of_work(a,last_block, data): global ROOT - new_block_index = last_block.index + 1 - new_block_timestamp = time.time() + if ROOT: + new_block_index = last_block.index + 1 + new_block_timestamp = time.time() NODE_PENDING_TRANSACTIONS = [] @@ -96,11 +98,12 @@ def leadingzeroes(digest): else: break return n - - effort, pow_hash = genhash() - start_time = time.time() - global work - lead = leadingzeroes(pow_hash.digest()) + lead = 0 + if ROOT: + effort, pow_hash = genhash() + start_time = time.time() + global work + lead = leadingzeroes(pow_hash.digest()) while lead < work: # Check if any node found the solution every 60 seconds @@ -136,19 +139,21 @@ def mine(a, blockchain, node_pending_transactions): is slowed down by a proof of work algorithm. """ # Get the last proof of work - last_block = BLOCKCHAIN[len(BLOCKCHAIN) - 1] + last_block = None + if ROOT: + last_block = BLOCKCHAIN[len(BLOCKCHAIN) - 1] - NODE_PENDING_TRANSACTIONS = requests.get( - "http://" + MINER_NODE_URL + ":" + str(PORT) + "/txion?update=" + user.public_key).content - NODE_PENDING_TRANSACTIONS = json.loads(NODE_PENDING_TRANSACTIONS) + NODE_PENDING_TRANSACTIONS = requests.get( + "http://" + MINER_NODE_URL + ":" + str(PORT) + "/txion?update=" + user.public_key).content + NODE_PENDING_TRANSACTIONS = json.loads(NODE_PENDING_TRANSACTIONS) - # Then we add the mining reward - NODE_PENDING_TRANSACTIONS.append({ - "from": "network", - "to": user.public_key, - "amount": 1.0}) + # Then we add the mining reward + NODE_PENDING_TRANSACTIONS.append({ + "from": "network", + "to": user.public_key, + "amount": 1.0}) - new_block_data = {"transactions": list(NODE_PENDING_TRANSACTIONS)} + new_block_data = {"transactions": list(NODE_PENDING_TRANSACTIONS)} proof = proof_of_work(a,last_block, new_block_data) if not proof[0]: BLOCKCHAIN = proof[1] From 8b9026d5ebe09ae94e380cd7977a9bac567e376d Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 16:52:51 -0400 Subject: [PATCH 36/56] Fixing networking --- simpleCoin/miner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index a25020e..15b4941 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -140,6 +140,7 @@ def mine(a, blockchain, node_pending_transactions): """ # Get the last proof of work last_block = None + new_block_data = None if ROOT: last_block = BLOCKCHAIN[len(BLOCKCHAIN) - 1] From ed3904d4852678ba37831ae963bde10f44f53ca6 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 16:55:14 -0400 Subject: [PATCH 37/56] Fixing networking --- simpleCoin/miner.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 15b4941..5271cee 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -105,9 +105,10 @@ def leadingzeroes(digest): global work lead = leadingzeroes(pow_hash.digest()) while lead < work: - + print(ROOT) # Check if any node found the solution every 60 seconds - if int((time.time() - start_time) % 60) == 0 or not ROOT: + if not ROOT or int((time.time() - start_time) % 60) == 0: + print("inside if") ROOT = True # If any other node got the proof, stop searching new_blockchain = consensus() From dff7c25b033892c1b6b44fb1e0131135e625136e Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 18:48:32 -0400 Subject: [PATCH 38/56] Fix Networking --- simpleCoin/Block.py | 2 ++ simpleCoin/miner.py | 40 +++++++++++++++++++++++++++------------- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/simpleCoin/Block.py b/simpleCoin/Block.py index fc041df..f457f18 100644 --- a/simpleCoin/Block.py +++ b/simpleCoin/Block.py @@ -69,6 +69,8 @@ def buildpow(index,timestamp,effort,data,previous_hash): m.update((str(index) + str(timestamp) + str(effort) + str(data) + str(previous_hash)).encode('utf-8')) return m def validate(block): + if block.index == 0: + return True pow = buildpow(block.index,block.timestamp,block.effort,block.data,block.previous_hash) if block.proof_of_work == pow.hexdigest(): return True diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 5271cee..75ba4af 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -202,30 +202,43 @@ def mine(a, blockchain, node_pending_transactions): def find_new_chains(): - # TODO maybe check the length of nodes before just downloading one at random. - # TODO also if it fails validation, I never want to use that person again. + print("find new chains") # Get the blockchains of every other node other_chains = [] for node_url in PEER_NODES: - blockchains = None - try: - blockchains = requests.get(node_url + ":" + PORT + "/blocks").content - except: - pass + + blockchain_json = None + found_blockchain = [] + url = "http://"+node_url + ":" + str(PORT) + "/blocks" + print("looking at ", url) + blockchain_json = requests.get(url).content + # Convert the JSON object to a Python dictionary - if blockchains is not None: - blockchains = json.loads(blockchains) + if blockchain_json is not None: + blockchain_json = json.loads(blockchain_json) + for block_json in blockchain_json: + temp = Block() + temp.importjson(block_json) + if validate(temp): + found_blockchain.append(temp) # Verify other node block is correct - validated = validate_blockchain(blockchains) + validated = validate_blockchain(found_blockchain) if validated: - other_chains.append(blockchains) + print("adding one from",node_url) + other_chains.append(found_blockchain) + else: + print("invalid blockchain") + else: + print("block_json does not have good data") + continue return other_chains def consensus(): - # TODO I should look at the hashes of my coins versus there's and then only validate when they differ if len(PEER_NODES) == 0: return False + else: + print("looking at nodes") global BLOCKCHAIN # Get the blocks from other nodes other_chains = find_new_chains() @@ -243,6 +256,7 @@ def consensus(): else: # Give up searching proof, update chain and start over again BLOCKCHAIN = longest_chain + print("set a new blockchain") return BLOCKCHAIN @@ -251,7 +265,7 @@ def validate_blockchain(blockchain): previous = "" for block in blockchain: - if not block.validate(work): + if not validate(block): return False for transaction in block.data['transactions']: if transaction['from'] == "network" and transaction['amount'] != 1: From d0f5289562da016224c9dec7c1df62bfa24c1325 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 18:57:02 -0400 Subject: [PATCH 39/56] removed printing, changed export --- simpleCoin/Block.py | 3 ++- simpleCoin/miner.py | 16 ++++------------ 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/simpleCoin/Block.py b/simpleCoin/Block.py index f457f18..dbc849c 100644 --- a/simpleCoin/Block.py +++ b/simpleCoin/Block.py @@ -1,4 +1,5 @@ import hashlib +import ast class Block(): def __init__(self, index=-1, timestamp=-1, pow=-1, effort=-1,data=-1, previous_hash=-1): """Returns a new Block object. Each block is "chained" to its previous @@ -53,7 +54,7 @@ def importjson(self,json): self.timestamp = json['timestamp'] self.proof_of_work = json['pow'] self.effort = json['effort'] - self.data = json['data'] + self.data = ast.literal_eval(json['data']) self.previous_hash = json['previous'] self.hash = self.hash_block() diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 75ba4af..9750d33 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -271,19 +271,11 @@ def validate_blockchain(blockchain): if transaction['from'] == "network" and transaction['amount'] != 1: return False if block.index == 0: - previous = block.hash continue - else: - m = hashlib.sha256() - # m.update((str(last_block.index) + str(last_block.timestamp) + str(data) + str(last_block.previous_hash)).encode('utf-8')) - m.update( - (str(block.index) + str(block.timestamp) + str(block.data) + str(block.previous_hash)).encode('utf-8')) - if m.hexdigest() != block.hash: - return False - if previous != block.previous_hash: - return False - previous = block.hash - + if previous != block.previous_hash: + return False + previous = block.hash + print("received good chain") return True From fe0d32e00e5353931f223967b060f9e375bb29e6 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 21:00:44 -0400 Subject: [PATCH 40/56] removed printing, changed export --- simpleCoin/Block.py | 15 ++++++++------- simpleCoin/miner.py | 27 +++++++++++++++++++++------ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/simpleCoin/Block.py b/simpleCoin/Block.py index dbc849c..db91789 100644 --- a/simpleCoin/Block.py +++ b/simpleCoin/Block.py @@ -40,7 +40,7 @@ def hash_block(self): def exportjson(self): return { - "index": str(self.index), + "index": eval(self.index), "timestamp": str(self.timestamp), "pow": str(self.proof_of_work), "effort": str(self.effort), @@ -50,17 +50,17 @@ def exportjson(self): } def importjson(self,json): - self.index = json['index'] - self.timestamp = json['timestamp'] - self.proof_of_work = json['pow'] - self.effort = json['effort'] + self.index = int(json['index']) + self.timestamp = float(json['timestamp']) + self.proof_of_work = str(json['pow']) + self.effort = str(json['effort']) self.data = ast.literal_eval(json['data']) - self.previous_hash = json['previous'] + self.previous_hash = str(json['previous']) self.hash = self.hash_block() def __repr__(self): #def __init__(self, index, timestamp, pow, effort,data, previous_hash): - return "Block({},{},'{}','{}',{},'{}')".format(self.index,self.timestamp,self.proof_of_work,self.effort,self.data,self.previous_hash) + return "Block({},{},'{}','{}',{},'{}') |".format(self.index,self.timestamp,self.proof_of_work,self.effort,self.data,self.previous_hash) def __str__(self): return "i: {} time: {} \tpow: {} effort: {} data: {} \tprevious: {} hash: {}".format(self.index, self.timestamp,self.proof_of_work, self.effort, self.data, self.previous_hash, self.hash) @@ -75,4 +75,5 @@ def validate(block): pow = buildpow(block.index,block.timestamp,block.effort,block.data,block.previous_hash) if block.proof_of_work == pow.hexdigest(): return True + print("bad block",block.index) return False \ No newline at end of file diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 9750d33..5bd13dc 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -70,6 +70,7 @@ def create_genesis_block(): # print("b0 =",repr(BLOCKCHAIN[0])) # print("#",BLOCKCHAIN[0]) def proof_of_work(a,last_block, data): + print("proof of work") global ROOT if ROOT: new_block_index = last_block.index + 1 @@ -79,6 +80,7 @@ def proof_of_work(a,last_block, data): def random_str(): + print("random string") # Generate a random size string from 3 - 27 characters long rand_str = '' for i in range(0, 1 + secrets.randbelow(25)): @@ -86,10 +88,12 @@ def random_str(): return rand_str def genhash(): + print("genhash") effort = random_str() return effort, buildpow(new_block_index,new_block_timestamp,effort,data,last_block.hash) def leadingzeroes(digest): + print("leading zeroes") n = 0 result = ''.join(format(x, '08b') for x in bytearray(digest)) for c in result: @@ -100,21 +104,25 @@ def leadingzeroes(digest): return n lead = 0 if ROOT: + print("if root") effort, pow_hash = genhash() start_time = time.time() global work lead = leadingzeroes(pow_hash.digest()) while lead < work: - print(ROOT) + if len(BLOCKCHAIN) == 0: + ROOT = False # Check if any node found the solution every 60 seconds if not ROOT or int((time.time() - start_time) % 60) == 0: print("inside if") ROOT = True # If any other node got the proof, stop searching new_blockchain = consensus() + print(new_blockchain) if new_blockchain: # (False: another node got proof first, new blockchain) return False, new_blockchain + print("under if") # generate new hash for next time effort, pow_hash = genhash() lead = leadingzeroes(pow_hash.digest()) @@ -160,7 +168,6 @@ def mine(a, blockchain, node_pending_transactions): if not proof[0]: BLOCKCHAIN = proof[1] a.put(BLOCKCHAIN) - requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/blocks?update=" + user.public_key) continue else: @@ -222,6 +229,7 @@ def find_new_chains(): if validate(temp): found_blockchain.append(temp) # Verify other node block is correct + print(found_blockchain) validated = validate_blockchain(found_blockchain) if validated: print("adding one from",node_url) @@ -265,16 +273,22 @@ def validate_blockchain(blockchain): previous = "" for block in blockchain: + if block.index == 0: + previous = block.hash + continue if not validate(block): + print("block not valid",block.index) return False - for transaction in block.data['transactions']: + + transactions = block.data['transactions'] + + for transaction in transactions: if transaction['from'] == "network" and transaction['amount'] != 1: + print("transaction not valid",block.index) return False - if block.index == 0: - continue if previous != block.previous_hash: + print("previous hash not valid",block.index) return False - previous = block.hash print("received good chain") return True @@ -343,6 +357,7 @@ def get_blocks(): BLOCKCHAIN = a.get() # print("block chain updated now",len(BLOCKCHAIN),"long") # print("b was not empty") + print("got a blockchain") chain_to_send = BLOCKCHAIN # Converts our blocks into dictionaries so we can send them as json objects later chain_to_send_json = [] From 52c78265262dc690fdf84019b7b686ba50327bc8 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 21:09:32 -0400 Subject: [PATCH 41/56] fixing network --- simpleCoin/Block.py | 6 +++--- simpleCoin/miner.py | 14 ++++---------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/simpleCoin/Block.py b/simpleCoin/Block.py index db91789..1b37fea 100644 --- a/simpleCoin/Block.py +++ b/simpleCoin/Block.py @@ -40,13 +40,13 @@ def hash_block(self): def exportjson(self): return { - "index": eval(self.index), + "index": str(self.index), "timestamp": str(self.timestamp), "pow": str(self.proof_of_work), "effort": str(self.effort), "data": str(self.data), "previous": str(self.previous_hash), - "hash": self.hash + "hash": str(self.hash) } def importjson(self,json): @@ -60,7 +60,7 @@ def importjson(self,json): def __repr__(self): #def __init__(self, index, timestamp, pow, effort,data, previous_hash): - return "Block({},{},'{}','{}',{},'{}') |".format(self.index,self.timestamp,self.proof_of_work,self.effort,self.data,self.previous_hash) + return "Block({},{},'{}','{}',{},'{}')".format(self.index,self.timestamp,self.proof_of_work,self.effort,self.data,self.previous_hash) def __str__(self): return "i: {} time: {} \tpow: {} effort: {} data: {} \tprevious: {} hash: {}".format(self.index, self.timestamp,self.proof_of_work, self.effort, self.data, self.previous_hash, self.hash) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 5bd13dc..6707b92 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -70,7 +70,6 @@ def create_genesis_block(): # print("b0 =",repr(BLOCKCHAIN[0])) # print("#",BLOCKCHAIN[0]) def proof_of_work(a,last_block, data): - print("proof of work") global ROOT if ROOT: new_block_index = last_block.index + 1 @@ -80,7 +79,6 @@ def proof_of_work(a,last_block, data): def random_str(): - print("random string") # Generate a random size string from 3 - 27 characters long rand_str = '' for i in range(0, 1 + secrets.randbelow(25)): @@ -88,12 +86,10 @@ def random_str(): return rand_str def genhash(): - print("genhash") effort = random_str() return effort, buildpow(new_block_index,new_block_timestamp,effort,data,last_block.hash) def leadingzeroes(digest): - print("leading zeroes") n = 0 result = ''.join(format(x, '08b') for x in bytearray(digest)) for c in result: @@ -104,7 +100,6 @@ def leadingzeroes(digest): return n lead = 0 if ROOT: - print("if root") effort, pow_hash = genhash() start_time = time.time() global work @@ -114,7 +109,6 @@ def leadingzeroes(digest): ROOT = False # Check if any node found the solution every 60 seconds if not ROOT or int((time.time() - start_time) % 60) == 0: - print("inside if") ROOT = True # If any other node got the proof, stop searching new_blockchain = consensus() @@ -122,12 +116,10 @@ def leadingzeroes(digest): if new_blockchain: # (False: another node got proof first, new blockchain) return False, new_blockchain - print("under if") # generate new hash for next time effort, pow_hash = genhash() lead = leadingzeroes(pow_hash.digest()) if not a.empty(): - print("got one") new_block = a.get() if validate(new_block) and new_block.previous_hash == BLOCKCHAIN[len(BLOCKCHAIN) - 1].previous_hash: BLOCKCHAIN.append(new_block) @@ -218,11 +210,13 @@ def find_new_chains(): found_blockchain = [] url = "http://"+node_url + ":" + str(PORT) + "/blocks" print("looking at ", url) - blockchain_json = requests.get(url).content + blockchain_json = requests.get(url) # Convert the JSON object to a Python dictionary if blockchain_json is not None: - blockchain_json = json.loads(blockchain_json) + print(blockchain_json) + blockchain_json = json.loads(blockchain_json.content) + for block_json in blockchain_json: temp = Block() temp.importjson(block_json) From 676d83f04eb15ce4c57a57a54ae203bb46b0ed02 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 21:11:08 -0400 Subject: [PATCH 42/56] fixing network --- simpleCoin/miner.py | 1 - 1 file changed, 1 deletion(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 6707b92..00d6c28 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -112,7 +112,6 @@ def leadingzeroes(digest): ROOT = True # If any other node got the proof, stop searching new_blockchain = consensus() - print(new_blockchain) if new_blockchain: # (False: another node got proof first, new blockchain) return False, new_blockchain From 9a5f1f0d468fd33d635a5e63a95bd1e559a195ef Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 21:15:58 -0400 Subject: [PATCH 43/56] fixing network --- simpleCoin/miner.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 00d6c28..c99229f 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -29,9 +29,9 @@ node = Flask(__name__) node.config['SECRET_KEY'] = user.secret_key -work = 14 +WORK = 16 try: - assert work > 0 and work < 65 + assert WORK > 0 and WORK < 65 except AssertionError: print("Work value must be greater than 0 and less than 65") @@ -40,8 +40,8 @@ def create_genesis_block(): """To create each block, it needs the hash of the previous one. First block has no previous, so it must be created manually (with index zero and arbitrary previous hash)""" - global work - work_ez = int(work / 4) + 1 + global WORK + work_ez = int(WORK / 4) + 1 pow = "0" * work_ez pad = "1337" for i in range(4, 64): @@ -102,9 +102,9 @@ def leadingzeroes(digest): if ROOT: effort, pow_hash = genhash() start_time = time.time() - global work + global WORK lead = leadingzeroes(pow_hash.digest()) - while lead < work: + while lead < WORK: if len(BLOCKCHAIN) == 0: ROOT = False # Check if any node found the solution every 60 seconds @@ -131,7 +131,7 @@ def leadingzeroes(digest): def mine(a, blockchain, node_pending_transactions): global BLOCKCHAIN - global work + global WORK NODE_PENDING_TRANSACTIONS = node_pending_transactions while True: """Mining is the only way that new coins can be created. @@ -262,13 +262,16 @@ def consensus(): def validate_blockchain(blockchain): - global work + global WORK previous = "" - for block in blockchain: + for i in range(0,BLOCKCHAIN[len(BLOCKCHAIN)]): + block = BLOCKCHAIN[i] if block.index == 0: previous = block.hash continue + else: + previous = block[i-1].hash if not validate(block): print("block not valid",block.index) return False From 72e7d010da1c750bb39ab6cce0fb4ae0155f473d Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 21:17:53 -0400 Subject: [PATCH 44/56] fix networking --- simpleCoin/miner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index c99229f..dbcdcc0 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -265,7 +265,7 @@ def validate_blockchain(blockchain): global WORK previous = "" - for i in range(0,BLOCKCHAIN[len(BLOCKCHAIN)]): + for i in range(0,len(BLOCKCHAIN)-1): block = BLOCKCHAIN[i] if block.index == 0: previous = block.hash From c31eae97b3754da253bf87c33771c1bc46375411 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 21:22:42 -0400 Subject: [PATCH 45/56] removed printing, changed export --- .gitignore | 4 +++- simpleCoin/miner.py | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index e3320ff..8096062 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ *.pyc -simpleCoin/scratch.py +*scratch.py xyf.txt +*user.py +*miner_config.py \ No newline at end of file diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index dbcdcc0..4f7b98b 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -160,6 +160,7 @@ def mine(a, blockchain, node_pending_transactions): BLOCKCHAIN = proof[1] a.put(BLOCKCHAIN) requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/blocks?update=" + user.public_key) + print("back to mining") continue else: mined_block = proof[1] @@ -213,9 +214,7 @@ def find_new_chains(): # Convert the JSON object to a Python dictionary if blockchain_json is not None: - print(blockchain_json) blockchain_json = json.loads(blockchain_json.content) - for block_json in blockchain_json: temp = Block() temp.importjson(block_json) @@ -244,6 +243,7 @@ def consensus(): # Get the blocks from other nodes other_chains = find_new_chains() # If our chain isn't longest, then we store the longest chain + print("continue censensus with other_chains") longest_chain = BLOCKCHAIN for chain in other_chains: if longest_chain == BLOCKCHAIN: @@ -253,6 +253,7 @@ def consensus(): # If the longest chain wasn't ours, then we set our chain to the longest if longest_chain == BLOCKCHAIN: # Keep searching for proof + print("did not find one") return False else: # Give up searching proof, update chain and start over again From 31627dc45534555e41d4648a9a1142b395531b68 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 21:24:09 -0400 Subject: [PATCH 46/56] removed printing, changed export --- simpleCoin/miner.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 4f7b98b..49ea58e 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -251,15 +251,9 @@ def consensus(): if len(longest_chain) < len(chain): longest_chain = chain # If the longest chain wasn't ours, then we set our chain to the longest - if longest_chain == BLOCKCHAIN: - # Keep searching for proof - print("did not find one") - return False - else: - # Give up searching proof, update chain and start over again - BLOCKCHAIN = longest_chain - print("set a new blockchain") - return BLOCKCHAIN + BLOCKCHAIN = longest_chain + return BLOCKCHAIN + def validate_blockchain(blockchain): From 77ab0ade8485630b7eb9ce69f329bf9b8f5e3970 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 22:09:58 -0400 Subject: [PATCH 47/56] removed printing, changed export --- simpleCoin/miner.py | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 49ea58e..be3455b 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -71,6 +71,7 @@ def create_genesis_block(): # print("#",BLOCKCHAIN[0]) def proof_of_work(a,last_block, data): global ROOT + print(ROOT) if ROOT: new_block_index = last_block.index + 1 new_block_timestamp = time.time() @@ -111,15 +112,20 @@ def leadingzeroes(digest): if not ROOT or int((time.time() - start_time) % 60) == 0: ROOT = True # If any other node got the proof, stop searching - new_blockchain = consensus() + new_blockchain = consensus(a) if new_blockchain: # (False: another node got proof first, new blockchain) + print("returning") return False, new_blockchain # generate new hash for next time effort, pow_hash = genhash() lead = leadingzeroes(pow_hash.digest()) if not a.empty(): - new_block = a.get() + qget = a.get() + + qfrom = qget[0] + print("qfrom") + new_block = qget[1] if validate(new_block) and new_block.previous_hash == BLOCKCHAIN[len(BLOCKCHAIN) - 1].previous_hash: BLOCKCHAIN.append(new_block) return False, BLOCKCHAIN @@ -158,8 +164,6 @@ def mine(a, blockchain, node_pending_transactions): proof = proof_of_work(a,last_block, new_block_data) if not proof[0]: BLOCKCHAIN = proof[1] - a.put(BLOCKCHAIN) - requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/blocks?update=" + user.public_key) print("back to mining") continue else: @@ -189,7 +193,7 @@ def mine(a, blockchain, node_pending_transactions): ''' BLOCKCHAIN.append(mined_block) - a.put(BLOCKCHAIN) + a.put(["mined_lower",BLOCKCHAIN]) requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/blocks?update=" + user.public_key) for node in PEER_NODES: @@ -221,7 +225,6 @@ def find_new_chains(): if validate(temp): found_blockchain.append(temp) # Verify other node block is correct - print(found_blockchain) validated = validate_blockchain(found_blockchain) if validated: print("adding one from",node_url) @@ -234,7 +237,8 @@ def find_new_chains(): return other_chains -def consensus(): +def consensus(a): + global ROOT if len(PEER_NODES) == 0: return False else: @@ -243,8 +247,14 @@ def consensus(): # Get the blocks from other nodes other_chains = find_new_chains() # If our chain isn't longest, then we store the longest chain - print("continue censensus with other_chains") + if len(other_chains) == 1: + BLOCKCHAIN = other_chains + a.put(["consensus",BLOCKCHAIN]) + requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/blocks?update=" + user.public_key) + ROOT = True + return other_chains[0] longest_chain = BLOCKCHAIN + for chain in other_chains: if longest_chain == BLOCKCHAIN: continue @@ -266,7 +276,7 @@ def validate_blockchain(blockchain): previous = block.hash continue else: - previous = block[i-1].hash + previous = BLOCKCHAIN[i-1].hash if not validate(block): print("block not valid",block.index) return False @@ -323,7 +333,7 @@ def get_block(): # print(new_block) if validate(new_block) and new_block.previous_hash == BLOCKCHAIN[len(BLOCKCHAIN)-1].previous_hash: print("Validated") - a.put(new_block) + a.put(["get_block",new_block]) BLOCKCHAIN.append(new_block) else: print("Did not validate") @@ -345,10 +355,14 @@ def get_blocks(): if request.args.get("update") == user.public_key: # print("updating /blocks") - BLOCKCHAIN = a.get() + qget= a.get() + qfrom = qget[0] + print(qfrom) + BLOCKCHAIN = qget[1] # print("block chain updated now",len(BLOCKCHAIN),"long") # print("b was not empty") print("got a blockchain") + print(type(BLOCKCHAIN[0])) chain_to_send = BLOCKCHAIN # Converts our blocks into dictionaries so we can send them as json objects later chain_to_send_json = [] From 0abf3957be665ce6553d2f30b0ff928a48dafd5f Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 22:15:54 -0400 Subject: [PATCH 48/56] fixing networking --- simpleCoin/miner.py | 52 ++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index be3455b..119c96c 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -237,32 +237,7 @@ def find_new_chains(): return other_chains -def consensus(a): - global ROOT - if len(PEER_NODES) == 0: - return False - else: - print("looking at nodes") - global BLOCKCHAIN - # Get the blocks from other nodes - other_chains = find_new_chains() - # If our chain isn't longest, then we store the longest chain - if len(other_chains) == 1: - BLOCKCHAIN = other_chains - a.put(["consensus",BLOCKCHAIN]) - requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/blocks?update=" + user.public_key) - ROOT = True - return other_chains[0] - longest_chain = BLOCKCHAIN - for chain in other_chains: - if longest_chain == BLOCKCHAIN: - continue - if len(longest_chain) < len(chain): - longest_chain = chain - # If the longest chain wasn't ours, then we set our chain to the longest - BLOCKCHAIN = longest_chain - return BLOCKCHAIN @@ -345,7 +320,32 @@ def get_block(): return "200" +def consensus(a): + global ROOT + if len(PEER_NODES) == 0: + return False + else: + print("looking at nodes") + global BLOCKCHAIN + # Get the blocks from other nodes + other_chains = find_new_chains() + # If our chain isn't longest, then we store the longest chain + if len(other_chains) == 1: + BLOCKCHAIN = other_chains[0] + a.put(["consensus",BLOCKCHAIN]) + requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/blocks?update=" + user.public_key) + ROOT = True + return BLOCKCHAIN + longest_chain = BLOCKCHAIN + for chain in other_chains: + if longest_chain == BLOCKCHAIN: + continue + if len(longest_chain) < len(chain): + longest_chain = chain + # If the longest chain wasn't ours, then we set our chain to the longest + BLOCKCHAIN = longest_chain + return BLOCKCHAIN @node.route('/blocks', methods=['GET']) @@ -357,7 +357,7 @@ def get_blocks(): qget= a.get() qfrom = qget[0] - print(qfrom) + print("get_block",qfrom) BLOCKCHAIN = qget[1] # print("block chain updated now",len(BLOCKCHAIN),"long") # print("b was not empty") From c57a8525ee527bcf7bbcbebdfe5ae1e542c7f65e Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 22:19:27 -0400 Subject: [PATCH 49/56] fixed netorking? --- simpleCoin/miner.py | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 119c96c..b24995e 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -63,15 +63,11 @@ def create_genesis_block(): BLOCKCHAIN = [] ROOT = False if len(PEER_NODES) == 0: - print("Root is true") ROOT = True BLOCKCHAIN.append(create_genesis_block()) -# print("b0 =",repr(BLOCKCHAIN[0])) -# print("#",BLOCKCHAIN[0]) def proof_of_work(a,last_block, data): global ROOT - print(ROOT) if ROOT: new_block_index = last_block.index + 1 new_block_timestamp = time.time() @@ -114,8 +110,6 @@ def leadingzeroes(digest): # If any other node got the proof, stop searching new_blockchain = consensus(a) if new_blockchain: - # (False: another node got proof first, new blockchain) - print("returning") return False, new_blockchain # generate new hash for next time effort, pow_hash = genhash() @@ -124,7 +118,6 @@ def leadingzeroes(digest): qget = a.get() qfrom = qget[0] - print("qfrom") new_block = qget[1] if validate(new_block) and new_block.previous_hash == BLOCKCHAIN[len(BLOCKCHAIN) - 1].previous_hash: BLOCKCHAIN.append(new_block) @@ -164,7 +157,6 @@ def mine(a, blockchain, node_pending_transactions): proof = proof_of_work(a,last_block, new_block_data) if not proof[0]: BLOCKCHAIN = proof[1] - print("back to mining") continue else: mined_block = proof[1] @@ -205,7 +197,6 @@ def mine(a, blockchain, node_pending_transactions): def find_new_chains(): - print("find new chains") # Get the blockchains of every other node other_chains = [] for node_url in PEER_NODES: @@ -213,7 +204,6 @@ def find_new_chains(): blockchain_json = None found_blockchain = [] url = "http://"+node_url + ":" + str(PORT) + "/blocks" - print("looking at ", url) blockchain_json = requests.get(url) # Convert the JSON object to a Python dictionary @@ -227,12 +217,7 @@ def find_new_chains(): # Verify other node block is correct validated = validate_blockchain(found_blockchain) if validated: - print("adding one from",node_url) other_chains.append(found_blockchain) - else: - print("invalid blockchain") - else: - print("block_json does not have good data") continue return other_chains @@ -253,26 +238,19 @@ def validate_blockchain(blockchain): else: previous = BLOCKCHAIN[i-1].hash if not validate(block): - print("block not valid",block.index) return False transactions = block.data['transactions'] for transaction in transactions: if transaction['from'] == "network" and transaction['amount'] != 1: - print("transaction not valid",block.index) return False if previous != block.previous_hash: - print("previous hash not valid",block.index) return False - print("received good chain") return True def validate_signature(public_key, signature, message): - # global BLOCKCHAIN - # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: - # print("verify_signature") """Verifies if the signature is correct. This is used to prove it's you (and not someone else) trying to do a transaction with your address. Called when a user tries to submit a new transaction. @@ -305,18 +283,14 @@ def get_block(): new_block_json = request.get_json() new_block = Block() new_block.importjson(new_block_json) - # print(new_block) if validate(new_block) and new_block.previous_hash == BLOCKCHAIN[len(BLOCKCHAIN)-1].previous_hash: - print("Validated") a.put(["get_block",new_block]) BLOCKCHAIN.append(new_block) else: - print("Did not validate") return "500" ip = request.remote_addr if str(ip) != "127.0.0.1" and ip not in PEER_NODES: PEER_NODES.append(str(ip)) - # print("adding",ip,"to peers list") return "200" @@ -324,8 +298,6 @@ def consensus(a): global ROOT if len(PEER_NODES) == 0: return False - else: - print("looking at nodes") global BLOCKCHAIN # Get the blocks from other nodes other_chains = find_new_chains() @@ -353,16 +325,9 @@ def get_blocks(): global BLOCKCHAIN # Load current blockchain. Only you should update your blockchain if request.args.get("update") == user.public_key: - # print("updating /blocks") - qget= a.get() qfrom = qget[0] - print("get_block",qfrom) BLOCKCHAIN = qget[1] - # print("block chain updated now",len(BLOCKCHAIN),"long") - # print("b was not empty") - print("got a blockchain") - print(type(BLOCKCHAIN[0])) chain_to_send = BLOCKCHAIN # Converts our blocks into dictionaries so we can send them as json objects later chain_to_send_json = [] @@ -371,16 +336,11 @@ def get_blocks(): # Send our chain to whomever requested it chain_to_send = json.dumps(chain_to_send_json) - # print("chain sent to ",request.remote_addr) return chain_to_send @node.route('/txion', methods=['GET', 'POST']) def transaction(): - # global BLOCKCHAIN - # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: - # print("transaction") - if request.method == 'POST': # On each new POST request, we extract the transaction data new_txion = request.get_json() @@ -417,8 +377,6 @@ def transaction(): @node.route('/balances', methods=['GET']) def get_balance(): global BLOCKCHAIN - # if BLOCKCHAIN[len(BLOCKCHAIN) - 1].index > 0: - # print("Balances") working = BLOCKCHAIN balances = {} balances_json = [] From c857e1bd8a3db7119fd8658c41c210614924673e Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 22:24:19 -0400 Subject: [PATCH 50/56] dammit --- simpleCoin/miner.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index b24995e..5519b91 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -119,6 +119,7 @@ def leadingzeroes(digest): qfrom = qget[0] new_block = qget[1] + print("received a block",qfrom) if validate(new_block) and new_block.previous_hash == BLOCKCHAIN[len(BLOCKCHAIN) - 1].previous_hash: BLOCKCHAIN.append(new_block) return False, BLOCKCHAIN @@ -280,17 +281,21 @@ def welcome_msg(): @node.route('/block', methods=['post']) def get_block(): global BLOCKCHAIN + ip = request.remote_addr new_block_json = request.get_json() new_block = Block() + print("trying to receieve a block from",ip) new_block.importjson(new_block_json) if validate(new_block) and new_block.previous_hash == BLOCKCHAIN[len(BLOCKCHAIN)-1].previous_hash: a.put(["get_block",new_block]) + if str(ip) != "127.0.0.1" and ip not in PEER_NODES: + print("added",ip) + PEER_NODES.append(str(ip)) BLOCKCHAIN.append(new_block) else: return "500" - ip = request.remote_addr - if str(ip) != "127.0.0.1" and ip not in PEER_NODES: - PEER_NODES.append(str(ip)) + + return "200" From 2c1ecc1f506ce024d51f8b22f951f040f902e47e Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 22:29:47 -0400 Subject: [PATCH 51/56] dammit --- simpleCoin/miner.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 5519b91..0dd1b4e 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -286,13 +286,15 @@ def get_block(): new_block = Block() print("trying to receieve a block from",ip) new_block.importjson(new_block_json) - if validate(new_block) and new_block.previous_hash == BLOCKCHAIN[len(BLOCKCHAIN)-1].previous_hash: + validation = validate(new_block) + if validation and new_block.previous_hash == BLOCKCHAIN[len(BLOCKCHAIN)-1].previous_hash: a.put(["get_block",new_block]) if str(ip) != "127.0.0.1" and ip not in PEER_NODES: print("added",ip) PEER_NODES.append(str(ip)) BLOCKCHAIN.append(new_block) else: + print("val",validation, "nbph",new_block.previous_hash,"aph",BLOCKCHAIN[len(BLOCKCHAIN)-1].previous_hash) return "500" @@ -313,15 +315,6 @@ def consensus(a): requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/blocks?update=" + user.public_key) ROOT = True return BLOCKCHAIN - longest_chain = BLOCKCHAIN - - for chain in other_chains: - if longest_chain == BLOCKCHAIN: - continue - if len(longest_chain) < len(chain): - longest_chain = chain - # If the longest chain wasn't ours, then we set our chain to the longest - BLOCKCHAIN = longest_chain return BLOCKCHAIN From 663bf049057a5bd1bba211737c1e21360c008e52 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 22:34:29 -0400 Subject: [PATCH 52/56] removed printing, changed export --- simpleCoin/miner.py | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 0dd1b4e..aacc27d 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -29,7 +29,7 @@ node = Flask(__name__) node.config['SECRET_KEY'] = user.secret_key -WORK = 16 +WORK = 20 try: assert WORK > 0 and WORK < 65 except AssertionError: @@ -83,6 +83,8 @@ def random_str(): return rand_str def genhash(): + if int((time.time() - start_time) % 60) == 0: + print("get to mine bc is", len(BLOCKCHAIN)) effort = random_str() return effort, buildpow(new_block_index,new_block_timestamp,effort,data,last_block.hash) @@ -266,7 +268,21 @@ def validate_signature(public_key, signature, message): return False - +def consensus(a): + global ROOT + if len(PEER_NODES) == 0: + return False + global BLOCKCHAIN + # Get the blocks from other nodes + other_chains = find_new_chains() + # If our chain isn't longest, then we store the longest chain + if len(other_chains) == 1: + BLOCKCHAIN = other_chains[0] + a.put(["consensus",BLOCKCHAIN]) + requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/blocks?update=" + user.public_key) + ROOT = True + return BLOCKCHAIN + return BLOCKCHAIN def welcome_msg(): @@ -301,21 +317,7 @@ def get_block(): return "200" -def consensus(a): - global ROOT - if len(PEER_NODES) == 0: - return False - global BLOCKCHAIN - # Get the blocks from other nodes - other_chains = find_new_chains() - # If our chain isn't longest, then we store the longest chain - if len(other_chains) == 1: - BLOCKCHAIN = other_chains[0] - a.put(["consensus",BLOCKCHAIN]) - requests.get("http://" + MINER_NODE_URL + ":" + str(PORT) + "/blocks?update=" + user.public_key) - ROOT = True - return BLOCKCHAIN - return BLOCKCHAIN + @node.route('/blocks', methods=['GET']) From 6dc27c22d12a1214fa1790f0143fc2fd9e53ccc3 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 22:36:17 -0400 Subject: [PATCH 53/56] removed printing, changed export --- simpleCoin/miner.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index aacc27d..0879540 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -67,6 +67,7 @@ def create_genesis_block(): BLOCKCHAIN.append(create_genesis_block()) def proof_of_work(a,last_block, data): + start_time = time.time() global ROOT if ROOT: new_block_index = last_block.index + 1 @@ -100,7 +101,7 @@ def leadingzeroes(digest): lead = 0 if ROOT: effort, pow_hash = genhash() - start_time = time.time() + global WORK lead = leadingzeroes(pow_hash.digest()) while lead < WORK: From 5950ea655ea3dded89b29efe28948163a88884d2 Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 22:44:06 -0400 Subject: [PATCH 54/56] networking --- simpleCoin/miner.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index 0879540..bdf00c0 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -84,8 +84,6 @@ def random_str(): return rand_str def genhash(): - if int((time.time() - start_time) % 60) == 0: - print("get to mine bc is", len(BLOCKCHAIN)) effort = random_str() return effort, buildpow(new_block_index,new_block_timestamp,effort,data,last_block.hash) @@ -168,7 +166,7 @@ def mine(a, blockchain, node_pending_transactions): ''' String ''' - # print("#",mined_block) + print("#",mined_block) ''' String ''' @@ -329,6 +327,9 @@ def get_blocks(): qget= a.get() qfrom = qget[0] BLOCKCHAIN = qget[1] + ip = request.remote_addr + if str(ip) != "127.0.0.1" and ip not in PEER_NODES: + print("added", ip) chain_to_send = BLOCKCHAIN # Converts our blocks into dictionaries so we can send them as json objects later chain_to_send_json = [] From 5c06aedf6076b5c4f1ce6c3c9595b7be53ff293c Mon Sep 17 00:00:00 2001 From: HourGlss Date: Fri, 14 Sep 2018 22:45:27 -0400 Subject: [PATCH 55/56] removed printing, changed export --- simpleCoin/miner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/simpleCoin/miner.py b/simpleCoin/miner.py index bdf00c0..83eadc8 100644 --- a/simpleCoin/miner.py +++ b/simpleCoin/miner.py @@ -330,6 +330,7 @@ def get_blocks(): ip = request.remote_addr if str(ip) != "127.0.0.1" and ip not in PEER_NODES: print("added", ip) + PEER_NODES.append(str(ip)) chain_to_send = BLOCKCHAIN # Converts our blocks into dictionaries so we can send them as json objects later chain_to_send_json = [] From b89df0e60f8988c6c1fcc30fdf49a807a39f6d2a Mon Sep 17 00:00:00 2001 From: HourGlss <1668760+HourGlss@users.noreply.github.com> Date: Wed, 26 Sep 2018 22:03:12 -0400 Subject: [PATCH 56/56] simplecoin is broken --- README.md | 71 +------------------------------------------------------ 1 file changed, 1 insertion(+), 70 deletions(-) diff --git a/README.md b/README.md index 1c04ae2..c61c163 100644 --- a/README.md +++ b/README.md @@ -1,70 +1 @@ -# SimpleCoin -Just a really simple, insecure and incomplete implementation of a blockchain for a cryptocurrency made in Python. The goal of this project is to make a working blockchain currency, keeping it as simple as possible and to be used as educational material. - ->This project is just being made for fun. If you want to make your own cryptocurrency you should probably take a look at the [Bitcoin Repository](https://github.com/bitcoin/bitcoin). - - -## What is a blockchain? - -Taking a look at the [Bitcoin organization wiki website](https://en.bitcoin.it/wiki/Main_Page) we can find this definition: - ->A block chain is a transaction database shared by all nodes participating in a system based on the Bitcoin protocol. A full copy of a currency's block chain contains every transaction ever executed in the currency. With this information, one can find out how much value belonged to each address at any point in history. - -You can find more information in the original [Bitcoin Paper](https://bitcoin.org/bitcoin.pdf). - -## How to run it - -First, install ```requirements.txt```. - -``` -pip install -r requirements.txt -``` - -Then you have 2 options: - -- Run ```miner.py``` to become a node and start mining -- Run ```wallet.py``` to become a user and send transactions (to send transactions you must run a node, in other words, you must run ```miner.py``` too) - -> Important: DO NOT run it in the python IDLE, run it in your console. The ```miner.py``` uses parallel processing that doesn't work in the python IDLE. - -## How this code work? - -There are 2 main scripts: - -- ```miner.py``` -- ```wallet.py``` - -### Miner.py - -This file is probably the most important. Running it will create a node (like a server). From here you can connect to the blockchain and process transactions (that other users send) by mining. As a reward for this work, you recieve some coins. The more nodes exist, the more secure the blockchain gets. - -```miner.py``` has 2 processes running in parallel: - -1. The first process takes care of mining, updating new blockchains and finding the proof of work. - -2. The second process runs the flask server where peer nodes and users can connect to ask for the entire blockchain or sumbmit new transactions. - -> Parallel processes don't run in python IDLE, so make sure you are running it from the console. - -![miner](https://k60.kn3.net/3/B/3/F/E/C/013.png) - -### Wallet.py - -This file is for those who don't want to be nodes but simple users. Running this file allows you to generate a new address, send coins and check your transaction history (keep in mind that if you are running this in a local server, you will need a "miner" to process your transaction). -When creating a wallet address, a new file will be generated with all your security credentials. You are supposed to keep it safe. - -![wallet](https://k60.kn3.net/6/F/E/3/8/2/887.png) - - -## Contribution - -Major code modifcations by HourGlss to change proof of work, memory usage, enable networking, and blockchain validation - -Anybody is welcome to collaborate in this project. Feel free to push any pull request (even if you are new to coding). See ```CONTRIBUTING.md``` to learn how to contribute. - -Note: the idea of this project is to build a **really simple** blockchain system, so make sure all your code is easy to read (avoid too much code in 1 line) and don't introduce complex updates if they are not critical. In other words, keep it simple. - - -## Disclaimer - -By no means this project should be used for real purposes, it lacks security and may contain several bugs. +# SimpleCoin is fundamentally broken. HourCrypto is built on the same ideas, but works. look at that repo instead.