2
0

data.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. from tkinter import *
  2. from lib.chain import Chain, Block
  3. from lib.transaction import Transaction
  4. from lib.block import CURRENT
  5. import rpyc
  6. import time
  7. import json
  8. from create_keys import make_keys, get_private_key, get_plain_key
  9. import os
  10. from cryptography.hazmat.primitives import hashes
  11. from cryptography.hazmat.primitives.asymmetric import padding
  12. from cryptography.fernet import Fernet
  13. import rsa
  14. def new_contract():
  15. def add():
  16. name = str(title.get())
  17. if not os.path.isdir('contract_keys\\' + name):
  18. make_keys(name)
  19. pubkey = get_plain_key(name)
  20. # set discriptors of contract
  21. contract = {'id':pubkey,
  22. 'type':'init',
  23. 'date of initiation':time.time(),
  24. 'data': {'client':str(sender.get()),
  25. 'contractor':str(recipient.get()),
  26. 'discription':str(description.get()),
  27. 'name':name},
  28. 'terms' : {'deadline': int(deadline.get()),
  29. 'accepted': False,
  30. 'progress': '0%',
  31. 'price':int(price.get()),
  32. 'Sign time': 'not yet signed',
  33. 'comments':{}
  34. }
  35. }
  36. conn = rpyc.connect(host='localhost', port=42069, keepalive=True)
  37. t = Transaction()
  38. t.set_contract(contract)
  39. t.hash(contract=name)
  40. conn.root.push_transaction(t.serialize(out_json=True))
  41. conn.close()
  42. newWindow.destroy()
  43. else:
  44. print('Contract name already exists, choose another')
  45. newWindow.destroy()
  46. new_contract()
  47. newWindow = Tk()
  48. newWindow.title('Add contract')
  49. # create all text boxes
  50. Label(newWindow, text='Title: ').grid(row=0, column=0)
  51. title = Entry(newWindow, width=35, borderwidth=5)
  52. title.grid(row=0, column=1, columnspan=3, padx=10, pady=10)
  53. title.insert(0, 'test')
  54. Label(newWindow, text='Description: ').grid(row=1, column=0)
  55. description = Entry(newWindow, width=35, borderwidth=5)
  56. description.grid(row=1, column=1, columnspan=3, padx=10, pady=10)
  57. description.insert(0, 'test description')
  58. Label(newWindow, text='Deadline: ').grid(row=2, column=0)
  59. deadline = Entry(newWindow, width=35, borderwidth=5)
  60. deadline.grid(row=2, column=1, columnspan=3, padx=10, pady=10)
  61. deadline.insert(0, '1')
  62. Label(newWindow, text='Price: ').grid(row=3, column=0)
  63. price = Entry(newWindow, width=35, borderwidth=5)
  64. price.grid(row=3, column=1, columnspan=3, padx=10, pady=10)
  65. price.insert(0, '69420')
  66. Label(newWindow, text='Sender: ').grid(row=4, column=0)
  67. sender = Entry(newWindow, width=35, borderwidth=5)
  68. sender.grid(row=4, column=1, columnspan=3, padx=10, pady=10)
  69. sender.insert(0, 'justin')
  70. Label(newWindow, text='Recipient: ').grid(row=5, column=0)
  71. recipient = Entry(newWindow, width=35, borderwidth=5)
  72. recipient.grid(row=5, column=1, columnspan=3, padx=10, pady=10)
  73. recipient.insert(0, 'adam')
  74. # create the add contract button
  75. Button(newWindow, text = "Create contract", command=add).grid(row=6, column=1)
  76. def find_transaction():
  77. def find():
  78. conn = rpyc.connect(host='localhost', port=42069, keepalive=True)
  79. iden = get_plain_key(str(key.get()))
  80. transactions = [x.data for x in conn.root.find_transactions(iden)]
  81. transactions = decrypt_transactions(transactions, str(key.get()))
  82. print(current_contract_state(transactions, iden=iden))
  83. conn.close()
  84. newWindow.destroy()
  85. newWindow = Tk()
  86. newWindow.title('Add contract')
  87. Label(newWindow, text='Contract key: ').grid(row=0, column=0)
  88. key = Entry(newWindow, width=35, borderwidth=5)
  89. key.grid(row=0, column=1, columnspan=3, padx=10, pady=10)
  90. key.insert(0, '1')
  91. Button(newWindow, text='find contracts', command=find).grid(row=1, column=1)
  92. def add_term():
  93. def add():
  94. conn = rpyc.connect(host='localhost', port=42069, keepalive=True)
  95. iden = get_plain_key(str(contract.get()))
  96. attr = str(change.get())
  97. value = str(values.get())
  98. comment = str(comments.get())
  99. transactions = conn.root.find_transactions(iden)
  100. transactions = decrypt_transactions(transactions, str(contract.get()))
  101. state = current_contract_state(transactions, iden)
  102. if attr in state['data'] or attr in state['terms']:
  103. t = 'modify'
  104. else: t = 'update'
  105. # add new or updated info to block
  106. update = {'id':iden,
  107. 'update id':len(get_updates(transactions, iden=iden)),
  108. 'updated':attr,
  109. 'type':t,
  110. 'last update':time.time(),
  111. 'accepted': True,
  112. 'change':{attr:value}}
  113. # check if comment is passed and add it if necassary
  114. if comment:
  115. update['comment'] = comment
  116. t = Transaction()
  117. t.set_contract(update)
  118. t.hash(contract=iden)
  119. conn.root.push_transaction(t.serialize(out_json=True))
  120. #### TEST CODE PLEASE IGONRE ####
  121. update = {
  122. 'id':iden,
  123. 'update id':0,
  124. 'accept':True,
  125. 'type':'accept',
  126. 'last update':time.time()
  127. }
  128. if comment:
  129. update['comment'] = comment
  130. t = Transaction()
  131. t.set_contract(update)
  132. t.hash(contract=iden)
  133. conn.root.push_transaction(t.serialize(out_json=True))
  134. #### END TEST CODE PLEASE DONT IGONRE ####
  135. conn.close()
  136. newWindow.destroy()
  137. newWindow = Tk()
  138. newWindow.title('Add contract')
  139. # create all text boxes
  140. Label(newWindow, text='Contract: ').grid(row=0, column=0)
  141. contract = Entry(newWindow, width=35, borderwidth=5)
  142. contract.grid(row=0, column=1, columnspan=3, padx=10, pady=10)
  143. contract.insert(0, '1')
  144. Label(newWindow, text='What to change or add: ').grid(row=1, column=0)
  145. change = Entry(newWindow, width=35, borderwidth=5)
  146. change.grid(row=1, column=1, columnspan=3, padx=10, pady=10)
  147. change.insert(0, 'progress')
  148. Label(newWindow, text='New value: ').grid(row=2, column=0)
  149. values = Entry(newWindow, width=35, borderwidth=5)
  150. values.grid(row=2, column=1, columnspan=3, padx=10, pady=10)
  151. values.insert(0, '50%')
  152. Label(newWindow, text='comment (optional): ').grid(row=2, column=0)
  153. comments = Entry(newWindow, width=35, borderwidth=5)
  154. comments.grid(row=3, column=1, columnspan=3, padx=10, pady=10)
  155. comments.insert(0, 'dit is een comment')
  156. Button(newWindow, text='Add term', command=add).grid(row=4, column=1)
  157. def current_contract_state(transactions, iden):
  158. # set up contract state
  159. state = {'id':iden,
  160. 'data':{},
  161. 'terms':{}
  162. }
  163. # save not yet approved updates
  164. updates = {}
  165. # loop over all transaction in block
  166. for item in transactions:
  167. # save data about our project
  168. if item['id'] == iden:
  169. # set state to inital contract state
  170. if item['type'] == 'init':
  171. state = item
  172. continue
  173. # if update is not accept update, save it to updates dict
  174. if item['type'] != 'accept':
  175. # comments are always accepted
  176. if item['updated'] != 'comments':
  177. updates[item['update id']] = item
  178. continue
  179. # if accepted is true, retrieve update form dict and add to contract state
  180. elif item['accept'] == True:
  181. item = updates[item['update id']]
  182. # set attr to whatever has been updated
  183. attr = item['updated']
  184. # check if the update was removal
  185. if item['type'] == 'remove':
  186. # delete item in the right part of the dict
  187. try:
  188. if attr in state['data']:
  189. del state['data'][attr]
  190. else:
  191. del state['terms'][attr]
  192. except:
  193. pass
  194. if item['type'] == 'update':
  195. state['terms'][attr] = item['change'][attr]
  196. # check if updated attr is data or terms
  197. elif attr in state['data']:
  198. state['data'][attr] = item['change'][attr]
  199. elif attr in state['terms']:
  200. # special case for comments
  201. if attr == 'comments' and item['type'] not in ['remove', 'init']:
  202. k = list(item['change'][attr].keys())[0]
  203. state['terms'][attr][k] = item['change'][attr][k]
  204. # case for normal updates
  205. else:
  206. state['terms'][attr] = item['change'][attr]
  207. # special cases for last update and date of initiation
  208. elif 'last update' in item:
  209. state['last update'] = item['last update']
  210. return state
  211. def get_updates(transactions, iden=None, attr=None, accepted=None):
  212. updates = []
  213. # get all blocks and loop over transactions
  214. for item in transactions:
  215. # if attr is '' get updates for all attributes
  216. if attr == None:
  217. # if iden is None, get updates for all contracts
  218. # updates for all contracts and attrs
  219. if iden == None:
  220. if item['type'] != 'init':
  221. updates.append(item)
  222. # updates for specific contracts from all attr
  223. else:
  224. if item['type'] != 'init' and item['id'] == iden:
  225. updates.append(item)
  226. else:
  227. # updates for specific attrs from all contract
  228. if iden == None:
  229. if item['type'] != 'init' and item['updated'] == attr:
  230. updates.append(item)
  231. # updates for specific contract and specific attr
  232. else:
  233. if item['type'] != 'init' and item['updated'] == attr and item['id'] == iden:
  234. updates.append(item)
  235. return updates
  236. def decrypt_transactions(transactions, name):
  237. private_key = get_private_key(name)
  238. decrypted = []
  239. for encrypted in transactions:
  240. decrypted_key = rsa.decrypt(encrypted['encrypted key'],private_key)
  241. cipher = Fernet(decrypted_key)
  242. decrypted.append(cipher.decrypt(encrypted['data']))
  243. # old code
  244. # for encrypted in transactions:
  245. # decrypting_message = private_key.decrypt(
  246. # encrypted,
  247. # padding.OAEP(
  248. # mgf=padding.MGF1(algorithm=hashes.SHA256()),
  249. # algorithm=hashes.SHA256(),
  250. # label=None
  251. # )
  252. # )
  253. # decrypted.append(decrypting_message)
  254. return decrypted