| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387 |
- import json
- import os
- import time
- from tkinter import *
- import pprint
- import rpyc
- from create_keys import get_plain_key, get_private_key, make_keys
- from lib.block import CURRENT
- from lib.chain import Block, Chain
- from lib.transaction import Transaction
- from gui.encyption import decrypt_data
- # from gui.encyption import decrypt
- 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':{}
- }
- }
- t = Transaction()
- t.set_contract(contract)
- t.hash(contract=name)
- temp = t.serialize(out_json=True)
- conn = rpyc.connect(host='localhost', port=42069, keepalive=True)
- conn.root.push_transaction(temp)
- 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 = conn.root.find_transactions(iden)
- if len(transactions) == 0:
- print('No contract found')
- else:
- transactions = decrypt_transactions(transactions, str(key.get()))
- pprint.pprint(current_contract_state(transactions, iden=iden))
- conn.close()
- newWindow.destroy()
- newWindow = Tk()
- newWindow.title('Find 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, 'test')
- 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 value == '':
- t = 'remove'
- elif 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': False}
- if t != 'remove':
- update['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=str(contract.get()))
- conn.root.push_transaction(t.serialize(out_json=True))
- conn.close()
- newWindow.destroy()
- newWindow = Tk()
- newWindow.title('Add term')
- # 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, 'test')
- 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 (to remove, keep empty): ').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=3, 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 accept_updates():
- def show():
- conn = rpyc.connect(host='localhost', port=42069, keepalive=True)
- name = str(contract.get())
- transactions = conn.root.find_transactions(get_plain_key(name))
- transactions = decrypt_transactions(transactions, name)
- updates = retrieve_updates(transactions, name, accepted=False)
- conn.close()
- if len(updates) == 0:
- print('No updates to accept')
- else:
- print('Updates that still need to be accepted: \n')
- for update in updates:
- pprint.pprint(update)
- def accept():
- conn = rpyc.connect(host='localhost', port=42069, keepalive=True)
- name = str(contract.get())
- update_id = int(change.get())
- answer = accept_status.get()
- if answer == 'True':
- answer = True
- else: answer = False
- comment_text = str(comment.get())
- update = {
- 'id':get_plain_key(name),
- 'update id':update_id,
- 'accept':answer,
- 'type':'accept',
- 'last update':time.time()
- }
- if comment_text:
- update['comment'] = comment_text
- t = Transaction()
- t.set_contract(update)
- t.hash(contract=str(contract.get()))
- conn.root.push_transaction(t.serialize(out_json=True))
- conn.close()
- newWindow.destroy()
- newWindow = Tk()
- newWindow.title('Accept updates')
- 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, 'test')
- Label(newWindow, text='Id of update: ').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, '0')
- Label(newWindow, text='Awnser: ').grid(row=2, column=0)
- accept_status = StringVar(newWindow)
- accept_status.set('False') # default value
- OptionMenu(newWindow, accept_status, 'False', 'True').grid(row=2, column=1)
- Label(newWindow, text='Comment (optional): ').grid(row=3, column=0)
- comment = Entry(newWindow, width=35, borderwidth=5)
- comment.grid(row=3, column=1, columnspan=3, padx=10, pady=10)
- comment.insert(0, 'test test')
- Button(newWindow, text='Show updates to accept', command=show).grid(row=4, column=0, padx=10, pady=5)
- Button(newWindow, text='Accept', command=accept).grid(row=4, column=1, padx=10, pady=5)
- 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']]
-
- else: continue
-
- # 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 retrieve_updates(all_updates, iden, accepted=None):
- updates = {}
-
- for item in all_updates:
- if item['type'] == 'init':
- continue
- if item['type'] != 'accept' and item['updated'] != 'comments':
- updates[item['update id']] = item
- else:
- try:
- updates[item['update id']]['accepted'] = item['accept']
- except:
- pass
-
- if accepted == None:
- return updates
-
- return [updates[x] for x in list(updates.keys()) if updates[x]['accepted'] == accepted]
- def decrypt_transactions(transactions, name):
- return [json.loads(decrypt_data(name, x)) for x in transactions]
|