from tkinter import * from lib.chain import Chain, Block from lib.transaction import Transaction from lib.block import CURRENT import rpyc import time import json from create_keys import make_keys, get_private_key, get_plain_key import os from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import padding from cryptography.fernet import Fernet import rsa def new_contract(): def add(): name = str(title.get()) if not os.path.isdir('contract_keys\\' + name): make_keys(name) pubkey = get_plain_key(name) # set discriptors of contract contract = {'id':pubkey, 'type':'init', 'date of initiation':time.time(), 'data': {'client':str(sender.get()), 'contractor':str(recipient.get()), 'discription':str(description.get()), 'name':name}, 'terms' : {'deadline': int(deadline.get()), 'accepted': False, 'progress': '0%', 'price':int(price.get()), 'Sign time': 'not yet signed', 'comments':{} } } conn = rpyc.connect(host='localhost', port=42069, keepalive=True) t = Transaction() t.set_contract(contract) t.hash(contract=name) conn.root.push_transaction(t.serialize(out_json=True)) conn.close() newWindow.destroy() else: print('Contract name already exists, choose another') newWindow.destroy() new_contract() newWindow = Tk() newWindow.title('Add contract') # create all text boxes Label(newWindow, text='Title: ').grid(row=0, column=0) title = Entry(newWindow, width=35, borderwidth=5) title.grid(row=0, column=1, columnspan=3, padx=10, pady=10) title.insert(0, 'test') Label(newWindow, text='Description: ').grid(row=1, column=0) description = Entry(newWindow, width=35, borderwidth=5) description.grid(row=1, column=1, columnspan=3, padx=10, pady=10) description.insert(0, 'test description') Label(newWindow, text='Deadline: ').grid(row=2, column=0) deadline = Entry(newWindow, width=35, borderwidth=5) deadline.grid(row=2, column=1, columnspan=3, padx=10, pady=10) deadline.insert(0, '1') Label(newWindow, text='Price: ').grid(row=3, column=0) price = Entry(newWindow, width=35, borderwidth=5) price.grid(row=3, column=1, columnspan=3, padx=10, pady=10) price.insert(0, '69420') Label(newWindow, text='Sender: ').grid(row=4, column=0) sender = Entry(newWindow, width=35, borderwidth=5) sender.grid(row=4, column=1, columnspan=3, padx=10, pady=10) sender.insert(0, 'justin') Label(newWindow, text='Recipient: ').grid(row=5, column=0) recipient = Entry(newWindow, width=35, borderwidth=5) recipient.grid(row=5, column=1, columnspan=3, padx=10, pady=10) recipient.insert(0, 'adam') # create the add contract button Button(newWindow, text = "Create contract", command=add).grid(row=6, column=1) def find_transaction(): def find(): conn = rpyc.connect(host='localhost', port=42069, keepalive=True) iden = get_plain_key(str(key.get())) transactions = [x.data for x in conn.root.find_transactions(iden)] transactions = decrypt_transactions(transactions, str(key.get())) print(current_contract_state(transactions, iden=iden)) conn.close() newWindow.destroy() newWindow = Tk() newWindow.title('Add contract') Label(newWindow, text='Contract key: ').grid(row=0, column=0) key = Entry(newWindow, width=35, borderwidth=5) key.grid(row=0, column=1, columnspan=3, padx=10, pady=10) key.insert(0, '1') Button(newWindow, text='find contracts', command=find).grid(row=1, column=1) def add_term(): def add(): conn = rpyc.connect(host='localhost', port=42069, keepalive=True) iden = get_plain_key(str(contract.get())) attr = str(change.get()) value = str(values.get()) comment = str(comments.get()) transactions = conn.root.find_transactions(iden) transactions = decrypt_transactions(transactions, str(contract.get())) state = current_contract_state(transactions, iden) if attr in state['data'] or attr in state['terms']: t = 'modify' else: t = 'update' # add new or updated info to block update = {'id':iden, 'update id':len(get_updates(transactions, iden=iden)), 'updated':attr, 'type':t, 'last update':time.time(), 'accepted': True, 'change':{attr:value}} # check if comment is passed and add it if necassary if comment: update['comment'] = comment t = Transaction() t.set_contract(update) t.hash(contract=iden) conn.root.push_transaction(t.serialize(out_json=True)) #### TEST CODE PLEASE IGONRE #### update = { 'id':iden, 'update id':0, 'accept':True, 'type':'accept', 'last update':time.time() } if comment: update['comment'] = comment t = Transaction() t.set_contract(update) t.hash(contract=iden) conn.root.push_transaction(t.serialize(out_json=True)) #### END TEST CODE PLEASE DONT IGONRE #### conn.close() newWindow.destroy() newWindow = Tk() newWindow.title('Add contract') # create all text boxes Label(newWindow, text='Contract: ').grid(row=0, column=0) contract = Entry(newWindow, width=35, borderwidth=5) contract.grid(row=0, column=1, columnspan=3, padx=10, pady=10) contract.insert(0, '1') Label(newWindow, text='What to change or add: ').grid(row=1, column=0) change = Entry(newWindow, width=35, borderwidth=5) change.grid(row=1, column=1, columnspan=3, padx=10, pady=10) change.insert(0, 'progress') Label(newWindow, text='New value: ').grid(row=2, column=0) values = Entry(newWindow, width=35, borderwidth=5) values.grid(row=2, column=1, columnspan=3, padx=10, pady=10) values.insert(0, '50%') Label(newWindow, text='comment (optional): ').grid(row=2, column=0) comments = Entry(newWindow, width=35, borderwidth=5) comments.grid(row=3, column=1, columnspan=3, padx=10, pady=10) comments.insert(0, 'dit is een comment') Button(newWindow, text='Add term', command=add).grid(row=4, column=1) def current_contract_state(transactions, iden): # set up contract state state = {'id':iden, 'data':{}, 'terms':{} } # save not yet approved updates updates = {} # loop over all transaction in block for item in transactions: # save data about our project if item['id'] == iden: # set state to inital contract state if item['type'] == 'init': state = item continue # if update is not accept update, save it to updates dict if item['type'] != 'accept': # comments are always accepted if item['updated'] != 'comments': updates[item['update id']] = item continue # if accepted is true, retrieve update form dict and add to contract state elif item['accept'] == True: item = updates[item['update id']] # set attr to whatever has been updated attr = item['updated'] # check if the update was removal if item['type'] == 'remove': # delete item in the right part of the dict try: if attr in state['data']: del state['data'][attr] else: del state['terms'][attr] except: pass if item['type'] == 'update': state['terms'][attr] = item['change'][attr] # check if updated attr is data or terms elif attr in state['data']: state['data'][attr] = item['change'][attr] elif attr in state['terms']: # special case for comments if attr == 'comments' and item['type'] not in ['remove', 'init']: k = list(item['change'][attr].keys())[0] state['terms'][attr][k] = item['change'][attr][k] # case for normal updates else: state['terms'][attr] = item['change'][attr] # special cases for last update and date of initiation elif 'last update' in item: state['last update'] = item['last update'] return state def get_updates(transactions, iden=None, attr=None, accepted=None): updates = [] # get all blocks and loop over transactions for item in transactions: # if attr is '' get updates for all attributes if attr == None: # if iden is None, get updates for all contracts # updates for all contracts and attrs if iden == None: if item['type'] != 'init': updates.append(item) # updates for specific contracts from all attr else: if item['type'] != 'init' and item['id'] == iden: updates.append(item) else: # updates for specific attrs from all contract if iden == None: if item['type'] != 'init' and item['updated'] == attr: updates.append(item) # updates for specific contract and specific attr else: if item['type'] != 'init' and item['updated'] == attr and item['id'] == iden: updates.append(item) return updates def decrypt_transactions(transactions, name): private_key = get_private_key(name) decrypted = [] for encrypted in transactions: decrypted_key = rsa.decrypt(encrypted['encrypted key'],private_key) cipher = Fernet(decrypted_key) decrypted.append(cipher.decrypt(encrypted['data'])) # old code # for encrypted in transactions: # decrypting_message = private_key.decrypt( # encrypted, # padding.OAEP( # mgf=padding.MGF1(algorithm=hashes.SHA256()), # algorithm=hashes.SHA256(), # label=None # ) # ) # decrypted.append(decrypting_message) return decrypted