2
0

data.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. import json
  2. import os
  3. import time
  4. from tkinter import *
  5. import pprint
  6. import rpyc
  7. from create_keys import get_plain_key, get_private_key, make_keys
  8. from lib.block import CURRENT
  9. from lib.chain import Block, Chain
  10. from lib.transaction import Transaction
  11. from gui.encyption import decrypt_data
  12. # from gui.encyption import decrypt
  13. def new_contract():
  14. def add():
  15. name = str(title.get())
  16. if not os.path.isdir('contract_keys\\' + name):
  17. make_keys(name)
  18. pubkey = get_plain_key(name)
  19. # set discriptors of contract
  20. contract = {'id':pubkey,
  21. 'type':'init',
  22. 'date of initiation':time.time(),
  23. 'data': {'client':str(sender.get()),
  24. 'contractor':str(recipient.get()),
  25. 'discription':str(description.get()),
  26. 'name':name},
  27. 'terms' : {'deadline': int(deadline.get()),
  28. 'accepted': False,
  29. 'progress': '0%',
  30. 'price':int(price.get()),
  31. 'Sign time': 'not yet signed',
  32. 'comments':{}
  33. }
  34. }
  35. t = Transaction()
  36. t.set_contract(contract)
  37. t.hash(contract=name)
  38. temp = t.serialize(out_json=True)
  39. conn = rpyc.connect(host='localhost', port=42069, keepalive=True)
  40. conn.root.push_transaction(temp)
  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 = conn.root.find_transactions(iden)
  81. if len(transactions) == 0:
  82. print('No contract found')
  83. else:
  84. transactions = decrypt_transactions(transactions, str(key.get()))
  85. print('Current contract state')
  86. pprint.pprint(current_contract_state(transactions, iden=iden))
  87. conn.close()
  88. newWindow.destroy()
  89. def findall():
  90. conn = rpyc.connect(host='localhost', port=42069, keepalive=True)
  91. iden = get_plain_key(str(key.get()))
  92. transactions = conn.root.find_transactions(iden)
  93. if len(transactions) == 0:
  94. print('No contract found')
  95. else:
  96. transactions = decrypt_transactions(transactions, str(key.get()))
  97. print('All updates')
  98. for item in transactions:
  99. if item['type'] != 'init':
  100. pprint.pprint(item)
  101. print('\n')
  102. print('Current contract state')
  103. pprint.pprint(current_contract_state(transactions, iden=iden))
  104. conn.close()
  105. newWindow.destroy()
  106. newWindow = Tk()
  107. newWindow.title('Find contract')
  108. Label(newWindow, text='Contract key: ').grid(row=0, column=0)
  109. key = Entry(newWindow, width=35, borderwidth=5)
  110. key.grid(row=0, column=1, columnspan=3, padx=10, pady=10)
  111. key.insert(0, 'test')
  112. Button(newWindow, text='find contracts', command=find).grid(row=2, column=0)
  113. Button(newWindow, text='find contracts and updates', command=findall).grid(row=2, column=1)
  114. def add_term():
  115. def add():
  116. conn = rpyc.connect(host='localhost', port=42069, keepalive=True)
  117. iden = get_plain_key(str(contract.get()))
  118. attr = str(change.get())
  119. value = str(values.get())
  120. comment = str(comments.get())
  121. transactions = conn.root.find_transactions(iden)
  122. transactions = decrypt_transactions(transactions, str(contract.get()))
  123. state = current_contract_state(transactions, iden)
  124. if value == '':
  125. t = 'remove'
  126. elif attr in state['data'] or attr in state['terms']:
  127. t = 'modify'
  128. else: t = 'update'
  129. # add new or updated info to block
  130. update = {'id':iden,
  131. 'update id':len(get_updates(transactions, iden=iden)),
  132. 'updated':attr,
  133. 'type':t,
  134. 'last update':time.time(),
  135. 'accepted': False}
  136. if t != 'remove':
  137. update['change'] = {attr:value}
  138. # check if comment is passed and add it if necassary
  139. if comment:
  140. update['comment'] = comment
  141. t = Transaction()
  142. t.set_contract(update)
  143. t.hash(contract=str(contract.get()))
  144. conn.root.push_transaction(t.serialize(out_json=True))
  145. conn.close()
  146. newWindow.destroy()
  147. newWindow = Tk()
  148. newWindow.title('Add term')
  149. # create all text boxes
  150. Label(newWindow, text='Contract: ').grid(row=0, column=0)
  151. contract = Entry(newWindow, width=35, borderwidth=5)
  152. contract.grid(row=0, column=1, columnspan=3, padx=10, pady=10)
  153. contract.insert(0, 'test')
  154. Label(newWindow, text='What to change or add: ').grid(row=1, column=0)
  155. change = Entry(newWindow, width=35, borderwidth=5)
  156. change.grid(row=1, column=1, columnspan=3, padx=10, pady=10)
  157. change.insert(0, 'progress')
  158. Label(newWindow, text='New value (to remove, keep empty): ').grid(row=2, column=0)
  159. values = Entry(newWindow, width=35, borderwidth=5)
  160. values.grid(row=2, column=1, columnspan=3, padx=10, pady=10)
  161. values.insert(0, '50%')
  162. Label(newWindow, text='comment (optional): ').grid(row=3, column=0)
  163. comments = Entry(newWindow, width=35, borderwidth=5)
  164. comments.grid(row=3, column=1, columnspan=3, padx=10, pady=10)
  165. comments.insert(0, 'dit is een comment')
  166. Button(newWindow, text='Add term', command=add).grid(row=4, column=1)
  167. def accept_updates():
  168. def show():
  169. conn = rpyc.connect(host='localhost', port=42069, keepalive=True)
  170. name = str(contract.get())
  171. transactions = conn.root.find_transactions(get_plain_key(name))
  172. transactions = decrypt_transactions(transactions, name)
  173. updates = retrieve_updates(transactions, name, accepted=False)
  174. conn.close()
  175. if len(updates) == 0:
  176. print('No updates to accept')
  177. else:
  178. print('Updates that still need to be accepted: \n')
  179. for update in updates:
  180. pprint.pprint(update)
  181. def accept():
  182. conn = rpyc.connect(host='localhost', port=42069, keepalive=True)
  183. name = str(contract.get())
  184. update_id = int(change.get())
  185. answer = accept_status.get()
  186. if answer == 'True':
  187. answer = True
  188. else: answer = False
  189. comment_text = str(comment.get())
  190. update = {
  191. 'id':get_plain_key(name),
  192. 'update id':update_id,
  193. 'accept':answer,
  194. 'type':'accept',
  195. 'last update':time.time()
  196. }
  197. if comment_text:
  198. update['comment'] = comment_text
  199. t = Transaction()
  200. t.set_contract(update)
  201. t.hash(contract=str(contract.get()))
  202. conn.root.push_transaction(t.serialize(out_json=True))
  203. conn.close()
  204. newWindow.destroy()
  205. newWindow = Tk()
  206. newWindow.title('Accept updates')
  207. Label(newWindow, text='Contract: ').grid(row=0, column=0)
  208. contract = Entry(newWindow, width=35, borderwidth=5)
  209. contract.grid(row=0, column=1, columnspan=3, padx=10, pady=10)
  210. contract.insert(0, 'test')
  211. Label(newWindow, text='Id of update: ').grid(row=1, column=0)
  212. change = Entry(newWindow, width=35, borderwidth=5)
  213. change.grid(row=1, column=1, columnspan=3, padx=10, pady=10)
  214. change.insert(0, '0')
  215. Label(newWindow, text='Awnser: ').grid(row=2, column=0)
  216. accept_status = StringVar(newWindow)
  217. accept_status.set('False') # default value
  218. OptionMenu(newWindow, accept_status, 'False', 'True').grid(row=2, column=1)
  219. Label(newWindow, text='Comment (optional): ').grid(row=3, column=0)
  220. comment = Entry(newWindow, width=35, borderwidth=5)
  221. comment.grid(row=3, column=1, columnspan=3, padx=10, pady=10)
  222. comment.insert(0, 'test test')
  223. Button(newWindow, text='Show updates to accept', command=show).grid(row=4, column=0, padx=10, pady=5)
  224. Button(newWindow, text='Accept', command=accept).grid(row=4, column=1, padx=10, pady=5)
  225. def current_contract_state(transactions, iden):
  226. # set up contract state
  227. state = {'id':iden,
  228. 'data':{},
  229. 'terms':{}
  230. }
  231. # save not yet approved updates
  232. updates = {}
  233. # loop over all transaction in block
  234. for item in transactions:
  235. # save data about our project
  236. if item['id'] == iden:
  237. # set state to inital contract state
  238. if item['type'] == 'init':
  239. state = item
  240. continue
  241. # if update is not accept update, save it to updates dict
  242. if item['type'] != 'accept':
  243. # comments are always accepted
  244. if item['updated'] != 'comments':
  245. updates[item['update id']] = item
  246. continue
  247. # if accepted is true, retrieve update form dict and add to contract state
  248. elif item['accept'] == True:
  249. item = updates[item['update id']]
  250. else: continue
  251. # set attr to whatever has been updated
  252. attr = item['updated']
  253. # check if the update was removal
  254. if item['type'] == 'remove':
  255. # delete item in the right part of the dict
  256. try:
  257. if attr in state['data']:
  258. del state['data'][attr]
  259. else:
  260. del state['terms'][attr]
  261. except:
  262. pass
  263. if item['type'] == 'update':
  264. state['terms'][attr] = item['change'][attr]
  265. # check if updated attr is data or terms
  266. elif attr in state['data']:
  267. state['data'][attr] = item['change'][attr]
  268. elif attr in state['terms']:
  269. # special case for comments
  270. if attr == 'comments' and item['type'] not in ['remove', 'init']:
  271. k = list(item['change'][attr].keys())[0]
  272. state['terms'][attr][k] = item['change'][attr][k]
  273. # case for normal updates
  274. else:
  275. state['terms'][attr] = item['change'][attr]
  276. # special cases for last update and date of initiation
  277. elif 'last update' in item:
  278. state['last update'] = item['last update']
  279. return state
  280. def get_updates(transactions, iden=None, attr=None, accepted=None):
  281. updates = []
  282. # get all blocks and loop over transactions
  283. for item in transactions:
  284. # if attr is '' get updates for all attributes
  285. if attr == None:
  286. # if iden is None, get updates for all contracts
  287. # updates for all contracts and attrs
  288. if iden == None:
  289. if item['type'] != 'init':
  290. updates.append(item)
  291. # updates for specific contracts from all attr
  292. else:
  293. if item['type'] != 'init' and item['id'] == iden:
  294. updates.append(item)
  295. else:
  296. # updates for specific attrs from all contract
  297. if iden == None:
  298. if item['type'] != 'init' and item['updated'] == attr:
  299. updates.append(item)
  300. # updates for specific contract and specific attr
  301. else:
  302. if item['type'] != 'init' and item['updated'] == attr and item['id'] == iden:
  303. updates.append(item)
  304. return updates
  305. def retrieve_updates(all_updates, iden, accepted=None):
  306. updates = {}
  307. for item in all_updates:
  308. if item['type'] == 'init':
  309. continue
  310. if item['type'] != 'accept' and item['updated'] != 'comments':
  311. updates[item['update id']] = item
  312. else:
  313. try:
  314. updates[item['update id']]['accepted'] = item['accept']
  315. except:
  316. pass
  317. if accepted == None:
  318. return updates
  319. return [updates[x] for x in list(updates.keys()) if updates[x]['accepted'] == accepted]
  320. def decrypt_transactions(transactions, name):
  321. return [json.loads(decrypt_data(name, x)) for x in transactions]