SHARE
TWEET

Untitled

a guest Feb 22nd, 2019 81 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ##Import statements
  2. ###################################################################################
  3. from flask import Flask, jsonify, request
  4. import unittest
  5. from flask_testing import TestCase
  6. import json, hashlib
  7. from collections import OrderedDict
  8. import time
  9. import logging,sys
  10.  
  11. #################################################################################
  12. #Functions - you only need to modify the mine_block() function below
  13. #TO DO
  14. def mine_block():
  15.     global new_transactions
  16.     proof=0
  17.     tx=coinbase_transaction()
  18.     #new_transactions.append(tx)
  19.     mining_candidate=f'{proof}{new_transactions}'
  20.     #print(new_transactions)
  21.     #TO DO  - change mining difficulty so that first characters of the hash must begin with '00'
  22.     while hash_twice(mining_candidate)[:1] != '9':
  23.         proof=proof+1
  24.         mining_candidate=f'{proof}{new_transactions}'
  25.    
  26.     block_hash=hash_twice(mining_candidate)
  27.     block_header=mining_candidate
  28.     #Compute the Merkle Root Hash of the transactions
  29.     Merk_Tree = Merkle_Tree()
  30.     Merk_Tree.create_transaction_string(new_transactions)
  31.     root_hash=Merk_Tree.create_tree()
  32.     block=new_block(new_transactions,proof,chain[-1]["block_hash"],block_hash=block_hash,block_header=block_header,root_hash=root_hash)
  33.     new_transactions=[]
  34.     return block
  35.  
  36. #END TO DO
  37. ################################
  38. # 1. Declare the class tree
  39. class Merkle_Tree:
  40.  
  41.     # 2. Initiate the class object
  42.     def __init__(self,listoftransactions=None):
  43.         self.listoftransactions = listoftransactions
  44.         self.past_transaction = OrderedDict()
  45.     # 3. Create the Merkle Tree  
  46.     def create_transaction_string(self, transactions):
  47.         string_list=[]
  48.         if len(transactions)==0:
  49.             transactions=[{'sender': 'NULL', 'recipient': 'NULL', 'amount': 'NULL'}]
  50.         # Convert transaction JSON into string, hash functions need strings
  51.         for tx in transactions:
  52.             string=""
  53.             for odict in tx:
  54.                 string=string+json.dumps(odict)+":"+json.dumps(tx[odict])
  55.             string_list.append(string)
  56.         #return string_list
  57.         self.listoftransactions=string_list
  58.  
  59.     # 3. Create the Merkle Tree  
  60.     def create_tree(self):
  61.  
  62.         # 3.0 Continue on the declaration
  63.         listoftransactions = self.listoftransactions
  64.         past_transaction = self.past_transaction
  65.         temp_transaction = []
  66.        
  67.  
  68.         # 3.1 Loop until the list finishes
  69.         for index in range(0,len(listoftransactions),2):
  70.  
  71.             # 3.2 Get the most left element
  72.             current = listoftransactions[index]
  73.  
  74.             # 3.3 If there is still index left get the right of the left most element
  75.             if index+1 != len(listoftransactions):
  76.                 current_right = listoftransactions[index+1]
  77.  
  78.             # 3.4 If we reached the limit of the list then make a empty string
  79.             else:
  80.                 current_right = ''
  81.  
  82.             # 3.5 Apply the Hash 256 function to the current values
  83.             current_hash=hashlib.sha256(current.encode('utf-8'))
  84.             #current_hash = hashlib.sha256(current)
  85.  
  86.             # 3.6 If the current right hash is not a '' <- empty string
  87.             if current_right != '':
  88.                 #current_right_hash = hashlib.sha256(current_right)
  89.                 current_right_hash=hashlib.sha256(current_right.encode('utf-8'))
  90.  
  91.             # 3.7 Add the Transaction to the dictionary
  92.             past_transaction[listoftransactions[index]] = current_hash.hexdigest()
  93.  
  94.             # 3.8 If the next right is not empty
  95.             if current_right != '':
  96.                 past_transaction[listoftransactions[index+1]] = current_right_hash.hexdigest()
  97.  
  98.             # 3.9 Create the new list of transaction
  99.             if current_right != '':
  100.                 temp_transaction.append(current_hash.hexdigest() + current_right_hash.hexdigest())
  101.  
  102.             # 3.01 If the left most is an empty string then only add the current value
  103.             else:
  104.                 temp_transaction.append(current_hash.hexdigest())
  105.  
  106.         # 3.02 Update the variables and rerun the function again
  107.         if len(listoftransactions) != 1:
  108.             self.listoftransactions = temp_transaction
  109.             self.past_transaction = past_transaction
  110.  
  111.             # 3.03 Call the function repeatly again and again until we get the root
  112.             self.create_tree()
  113.         return self.Get_Root_leaf()
  114.  
  115.     # 4. Return the past Transaction
  116.     def Get_past_transaction(self):
  117.         return self.past_transaction
  118.  
  119.     # 5. Get the root of the transaction
  120.     def Get_Root_leaf(self):
  121.         last_key = list(self.past_transaction.keys())[-1]
  122.         return self.past_transaction[last_key]
  123. #######################
  124. def new_block(new_transactions,proof, previous_hash,block_hash,block_header,root_hash):
  125.        
  126.         if len(chain)==0:
  127.             new_transactions=[]
  128.    
  129.         #self.new_transactions = []
  130.  
  131.         #index1 is the current block number, which is the number of blocks on the chain +1
  132.         new_block = {
  133.             'index1': len(chain)+1,
  134.             'time': time.time(),
  135.             'proof_of_work': proof,
  136.             'previous_hash':previous_hash,
  137.             'transactions': new_transactions,
  138.             'transaction_hash_merkle_root':root_hash,
  139.             'version': version  
  140.         }
  141.        
  142.         new_block['block_hash']=block_hash
  143.         new_block['block_header']=block_header
  144.  
  145.         # Reset the current list of transactions
  146.         #new_transactions = []
  147.         # Attach block to the current
  148.         chain.append(new_block)
  149.         #save_block(new_block)
  150.         return new_block
  151.  
  152. def hash_twice(input_dictionary):
  153.     block_string = json.dumps(input_dictionary).encode()
  154.     return hashlib.sha256(hashlib.sha256(block_string).hexdigest().encode()).hexdigest()
  155.  
  156.  
  157. def coinbase_transaction():
  158.     tx=new_transaction("0", 'self', mining_reward)
  159.     return tx
  160.  
  161. def new_transaction(sender_public_key, recipient_public_key, amount_value):
  162.     transaction={
  163.     'sender_public_key': sender_public_key,
  164.     'recipient_public_key': recipient_public_key,
  165.     'amount_value': amount_value,
  166.     }
  167.     transaction_string=json.dumps(transaction)
  168.     hash=hashlib.sha256(transaction_string.encode()).hexdigest()
  169.     global new_transactions
  170.     new_transactions.append(transaction)
  171.     #Add the hash value to the transaction object, and return it to the caller of the API
  172.     transaction['transaction_hash']=hash
  173.     return transaction
  174.  
  175. def get_chain():
  176.  
  177.     return chain
  178. #####################################################################################
  179. ##Class Definition, to initiate out unit test
  180. class TestBlockchainAPI(TestCase):
  181.     #Instantiate the FLask web app
  182.     def create_app(self):
  183.         app = Flask(__name__)
  184.        
  185.  
  186.         @app.route('/mine', methods=['GET'])
  187.         def mine():
  188.             response=mine_block()
  189.             return jsonify(response), 200
  190.  
  191.         return app
  192.            
  193.     def test_mine_block(self):
  194.         with self.client:
  195.             response = self.client.get('/mine')
  196.             # Print the value of the response from the API end point
  197.             log= logging.getLogger( "TestBlockchainAPI" )
  198.             log.debug(' \r\r mining result is %r',response.json)
  199.             # Test #1: Does the API return a code "200"?
  200.             self.assertEqual(response.status_code, 200)
  201.  
  202. #####################################################################################
  203. #Global variables
  204. version='1.0'
  205. mining_reward=50
  206. chain=[]
  207. new_transactions=[]
  208. #Add a genesis block, this is the first block of the chain
  209. new_block(new_transactions=[],previous_hash='0', proof=1,block_hash='',block_header='',root_hash='')
  210.  
  211. #####################################################################################
  212. # Runs the tests.
  213. if __name__ == '__main__':
  214.     #Prepare to log messages from the Tests
  215.     logging.basicConfig( stream=sys.stderr )
  216.     logging.getLogger( "TestBlockchainAPI" ).setLevel( logging.DEBUG )
  217.  
  218.     suite = unittest.TestLoader().loadTestsFromTestCase(TestBlockchainAPI)
  219.     unittest.TextTestRunner(verbosity=4).run(suite)
  220.  
  221. ######################################################################################
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top