Advertisement
Guest User

Untitled

a guest
Feb 22nd, 2019
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.91 KB | None | 0 0
  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
  13. ####TO DO
  14.  
  15. def mine_block():
  16. global new_transactions
  17. proof=0
  18. tx=coinbase_transaction()
  19. #new_transactions.append(tx)
  20. mining_candidate=f'{proof}{new_transactions}'
  21. #print(new_transactions)
  22. while hash_twice(mining_candidate)[:2] !="00":
  23. #print(hash_twice(mining_candidate)[:2])
  24. proof=proof+1
  25. mining_candidate=f'{proof}{new_transactions}'
  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. ######################################################################################
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement